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]); } } }
void do_4index_2_2_tensor_products( bool forwards, const opTypes& optype, const opTypes& rhsType, const opTypes& lhsType, SpinBlock& big, SpinBlock* rhsBlock, SpinBlock* lhsBlock, std::ofstream& ofs, const std::vector<Matrix>& rotateMatrix, const StateInfo *stateinfo ) { Op_component_base& rhs_array = rhsBlock->get_op_array(rhsType); Op_component_base& lhs_array = lhsBlock->get_op_array(lhsType); assert ( (rhs_array.get_size() == 1) || (lhs_array.get_size() == 1) ); // Loop over all rhs operator indices //FIXME copy or reference? std::vector<boost::shared_ptr<SparseMatrix> > rhs_ops; for (int iidx = 0; iidx < rhs_array.get_size(); ++iidx) { rhs_ops = rhs_array.get_local_element(iidx); // Loop over all lhs operator indices std::vector<boost::shared_ptr<SparseMatrix> > lhs_ops; for (int idx = 0; idx < lhs_array.get_size(); ++idx) { lhs_ops = lhs_array.get_local_element(idx); int i = rhs_ops[0]->get_orbs()[0]; int j = rhs_ops[0]->get_orbs()[1]; int k = lhs_ops[0]->get_orbs()[0]; int l = lhs_ops[0]->get_orbs()[1]; // In parallel calculations not all operators are built on each proc if ( ! big.get_op_array(optype).has_local_index(i,j,k,l) ) continue; //pout << "p" << mpigetrank() << "; i,j,k,l = " << i << "," << j << "," << k << "," << l << endl; std::vector<boost::shared_ptr<SparseMatrix> > vec = big.get_op_array(optype).get_element(i,j,k,l); // Loop over rhs spin-op components for (int jjdx=0; jjdx < rhs_ops.size(); jjdx++) { boost::shared_ptr<SparseMatrix>& rhs_op = rhs_ops[jjdx]; assert( rhs_op->get_built() ); const SpinQuantum& spin_12 = rhs_op->get_deltaQuantum(0); // Loop over lhs spin-op components for (int jdx=0; jdx < lhs_ops.size(); jdx++) { boost::shared_ptr<SparseMatrix>& lhs_op = lhs_ops[jdx]; assert( lhs_op->get_built() ); std::string build_12 = rhs_op->get_build_pattern(); std::string build_34 = lhs_op->get_build_pattern(); std::string build_pattern = "(" + build_12 + build_34 + ")"; const SpinQuantum& spin_34 = lhs_op->get_deltaQuantum(0); // Allocate and build new operator for (int sx=0; sx < vec.size(); sx++) { boost::shared_ptr<SparseMatrix>& op = vec[sx]; std::vector<SpinQuantum> s1 = { op->get_quantum_ladder().at(build_pattern).at(0), op->get_quantum_ladder().at(build_pattern).at(1) }; std::vector<SpinQuantum> s2 = { spin_12, spin_34 }; // Select relevant spin components if ( s1 == s2 ) { finish_tensor_product( big, rhsBlock, *rhs_op, *lhs_op, *op, forwards, build_pattern ); // Renormalise operator op->renormalise_transform( rotateMatrix, stateinfo ); } } } } // Store spin-batch on disk if ( ! dmrginp.do_npdm_in_core() ) store_ops_on_disk( ofs, vec ); } } }
void SpinAdapted::InitBlocks::InitNewSystemBlock(SpinBlock &system, SpinBlock &systemDot, SpinBlock &newSystem, int leftState, int rightState, const int& sys_add, const bool &direct, int integralIndex, const Storagetype &storage, bool haveNormops, bool haveCompops, int constraint) { newSystem.set_integralIndex() = integralIndex; newSystem.default_op_components(direct, system, systemDot, haveNormops, haveCompops, leftState==rightState); newSystem.setstoragetype(storage); newSystem.BuildSumBlock (constraint, system, systemDot); p2out << "\t\t\t NewSystem block " << endl << newSystem << endl; newSystem.printOperatorSummary(); }
void SpinAdapted::InitBlocks::InitNewSystemBlock(SpinBlock &system, SpinBlock &systemDot, SpinBlock &newSystem, int leftState, int rightState, const int& sys_add, const bool &direct, int integralIndex, const Storagetype &storage, bool haveNormops, bool haveCompops, int constraint, const std::vector<SpinQuantum>& braquanta, const std::vector<SpinQuantum>& ketquanta) { newSystem.set_integralIndex() = integralIndex; newSystem.default_op_components(direct, system, systemDot, haveNormops, haveCompops, leftState==rightState); newSystem.setstoragetype(storage); newSystem.BuildSumBlock (constraint, system, systemDot,braquanta,ketquanta); if (dmrginp.outputlevel() > 0) { pout << "\t\t\t NewSystem block " << endl << newSystem << endl; newSystem.printOperatorSummary(); } }
void finish_tensor_trace( SpinBlock& b, SpinBlock* sysdot, SparseMatrix& sysdot_op, SparseMatrix& op, std::string& build_pattern ) { // Build and store new operator assert( ! op.get_built() ); op.set_built() = true; op.set_build_pattern() = build_pattern; //FIXME magic number 2 op.set_deltaQuantum(1, op.get_quantum_ladder().at( build_pattern ).at(2) ); op.allocate(b.get_stateInfo()); SpinAdapted::operatorfunctions::TensorTrace(sysdot, sysdot_op, &b, &(b.get_stateInfo()), op); }
void do_4index_tensor_trace( const opTypes& optype, SpinBlock& big, SpinBlock* sysdot, std::ofstream& ofs, const std::vector<Matrix>& rotateMatrix, const StateInfo *stateinfo ) { // Get pointer to sparse operator array Op_component_base& sysdot_array = sysdot->get_op_array(optype); // Open filesystem if necessary std::ifstream ifs; if ( (! dmrginp.do_npdm_in_core()) && sysdot->size() > 1 ) ifs.open( sysdot_array.get_filename().c_str(), std::ios::binary ); //FIXME need reference? don't want to copy? // Loop over all operator indices std::vector<boost::shared_ptr<SparseMatrix> > sysdot_ops; for (int idx = 0; idx < sysdot_array.get_size(); ++idx) { if ( dmrginp.do_npdm_in_core() || sysdot->size() <= 1) sysdot_ops = sysdot_array.get_local_element(idx); else //FIXME size sysdot_ops = get_ops_from_disk( ifs, sysdot_array.get_local_element(0).size() ); // Loop over spin-op components int i = sysdot_ops[0]->get_orbs()[0]; int j = sysdot_ops[0]->get_orbs()[1]; int k = sysdot_ops[0]->get_orbs()[2]; int l = sysdot_ops[0]->get_orbs()[3]; // In parallel calculations not all operators are built on each proc if ( ! big.get_op_array(optype).has_local_index(i,j,k,l) ) continue; //pout << "p" << mpigetrank() << "; i,j,k,l = " << i << "," << j << "," << k << "," << l << endl; std::vector<boost::shared_ptr<SparseMatrix> > new_ops = big.get_op_array(optype).get_element(i,j,k,l); for (int jdx=0; jdx < sysdot_ops.size(); jdx++) { boost::shared_ptr<SparseMatrix>& sysdot_op = sysdot_ops[jdx]; assert( sysdot_op->get_built() ); std::string build_pattern = sysdot_op->get_build_pattern(); // Allocate and build new operator for (int sx=0; sx < new_ops.size(); sx++) { boost::shared_ptr<SparseMatrix>& op = new_ops[sx]; std::vector<SpinQuantum> s1 = sysdot_op->get_quantum_ladder().at(build_pattern); std::vector<SpinQuantum> s2 = op->get_quantum_ladder().at(build_pattern); // Store spin component in correct location if ( s1 == s2 ) { finish_tensor_trace( big, sysdot, *sysdot_op, *op, build_pattern ); // Renormalise operator op->renormalise_transform( rotateMatrix, stateinfo ); } } } // Store spin-batch on disk if ( ! dmrginp.do_npdm_in_core() ) store_ops_on_disk( ofs, new_ops ); } // Close filesystem if necessary if ( ifs.is_open() ) ifs.close(); }
void SpinBlock::store (bool forward, const vector<int>& sites, SpinBlock& b, int left, int right, char *name) { Timer disktimer; std::string file; if(dmrginp.spinAdapted()) { if (forward) file = str(boost::format("%s%s%d%s%d%s%d%s%d%s%d%s%d%s") % dmrginp.save_prefix() % "/SpinBlock-forward-"% sites[0] % "-" % sites[sites.size()-1] % "." % left % "." % right % "." %b.integralIndex % "." % mpigetrank() % ".tmp" ); else file = str(boost::format("%s%s%d%s%d%s%d%s%d%s%d%s%d%s") % dmrginp.save_prefix() % "/SpinBlock-backward-"% sites[0] % "-" % sites[sites.size()-1] % "." % left % "." % right % "." %b.integralIndex % "." % mpigetrank() % ".tmp" ); } else { if (forward) file = str(boost::format("%s%s%d%s%d%s%d%s%d%s%d%s%d%s") % dmrginp.save_prefix() % "/SpinBlock-forward-"% (sites[0]/2) % "-" % (sites[sites.size()-1]/2) % "." % left % "." % right % "." %b.integralIndex % "." % mpigetrank() % ".tmp" ); else file = str(boost::format("%s%s%d%s%d%s%d%s%d%s%d%s%d%s") % dmrginp.save_prefix() % "/SpinBlock-backward-"% (sites[0]/2) % "-" % (sites[sites.size()-1]/2) % "." % left % "." % right % "." %b.integralIndex % "." % mpigetrank() % ".tmp" ); } p1out << "\t\t\t Saving block file :: " << file << endl; std::ofstream ofs(file.c_str(), std::ios::binary); int lstate = left; int rstate = right; if (mpigetrank()==0) { StateInfo::store(forward, sites, b.braStateInfo, lstate); StateInfo::store(forward, sites, b.ketStateInfo, rstate); } b.Save (ofs); ofs.close(); //p1out << "\t\t\t block save disk time " << disktimer.elapsedwalltime() << " " << disktimer.elapsedcputime() << endl; }
double SweepOnepdm::do_one(SweepParams &sweepParams, const bool &warmUp, const bool &forward, const bool &restart, const int &restartSize) { SpinBlock system; const int nroots = dmrginp.nroots(); std::vector<double> finalEnergy(nroots,0.); std::vector<double> finalEnergy_spins(nroots,0.); double finalError = 0.; Matrix onepdm(2*dmrginp.last_site(), 2*dmrginp.last_site());onepdm=0.0; for (int i=0; i<nroots; i++) for (int j=0; j<=i; j++) save_onepdm_binary(onepdm, i ,j); sweepParams.set_sweep_parameters(); // a new renormalisation sweep routine pout << ((forward) ? "\t\t\t Starting renormalisation sweep in forwards direction" : "\t\t\t Starting renormalisation sweep in backwards direction") << endl; pout << "\t\t\t ============================================================================ " << endl; InitBlocks::InitStartingBlock (system,forward, sweepParams.get_forward_starting_size(), sweepParams.get_backward_starting_size(), restartSize, restart, warmUp); sweepParams.set_block_iter() = 0; pout << "\t\t\t Starting block is :: " << endl << system << endl; SpinBlock::store (forward, system.get_sites(), system); // if restart, just restoring an existing block -- sweepParams.savestate(forward, system.get_sites().size()); bool dot_with_sys = true; sweepParams.set_guesstype() = TRANSPOSE; SpinBlock newSystem; BlockAndDecimate (sweepParams, system, newSystem, warmUp, dot_with_sys); pout.precision(12); pout << "\t\t\t The lowest sweep energy : "<< sweepParams.get_lowest_energy()[0]+dmrginp.get_coreenergy()<<endl; pout << "\t\t\t ============================================================================ " << endl; for (int i=0; i<nroots; i++) for (int j=0; j<=i; j++) { load_onepdm_binary(onepdm, i ,j); accumulate_onepdm(onepdm); save_onepdm_spatial_text(onepdm, i ,j); save_onepdm_text(onepdm, i ,j); save_onepdm_spatial_binary(onepdm, i ,j); } return sweepParams.get_lowest_energy()[0]; }
void build_3index_ops( const opTypes& optype, SpinBlock& big, const opTypes& lhsType1, const opTypes& lhsType2, const opTypes& rhsType1, const opTypes& rhsType2, const std::vector<Matrix>& rotateMatrix, const StateInfo *stateinfo ) { // 3-index output file //pout << "build_3index_op, ofs =" << big.get_op_array(optype).get_filename() << endl; std::ofstream ofs; if ( ! dmrginp.do_npdm_in_core() ) ofs.open( big.get_op_array(optype).get_filename().c_str(), std::ios::binary ); SpinBlock* sysBlock = big.get_leftBlock(); SpinBlock* dotBlock = big.get_rightBlock(); // All 3 orbitals on sys or dot block do_3index_tensor_trace( optype, big, sysBlock, ofs, rotateMatrix, stateinfo ); do_3index_tensor_trace( optype, big, dotBlock, ofs, rotateMatrix, stateinfo ); bool forwards = ! ( sysBlock->get_sites().at(0) > dotBlock->get_sites().at(0) ); // 2,1 partitioning if ( forwards ) { do_3index_1_2_tensor_products( forwards, optype, lhsType1, rhsType2, big, dotBlock, sysBlock, ofs, rotateMatrix, stateinfo ); do_3index_2_1_tensor_products( forwards, optype, lhsType2, rhsType1, big, dotBlock, sysBlock, ofs, rotateMatrix, stateinfo ); } else { do_3index_1_2_tensor_products( forwards, optype, lhsType1, rhsType2, big, sysBlock, dotBlock, ofs, rotateMatrix, stateinfo ); do_3index_2_1_tensor_products( forwards, optype, lhsType2, rhsType1, big, sysBlock, dotBlock, ofs, rotateMatrix, stateinfo ); } if ( ofs.is_open() ) ofs.close(); }
double SparseMatrix::memoryUsed(const SpinBlock& b) { StateInfo stateinfo = b.get_stateInfo(); double memory = 0.0; for (int i=0; i < stateinfo.quanta.size(); i++) for (int j=0; j<stateinfo.quanta.size(); j++) if (allowedQuantaMatrix(i,j) ) { memory += 8.0*operatorMatrix(i,j).Storage(); } return memory; }
//------------------------------------------------------------------------------------------------------------------------------------------------------------- // (Cre,Cre,Cre,Cre) //------------------------------------------------------------------------------------------------------------------------------------------------------------- void SpinAdapted::CreCreCreCre::build(const SpinBlock& b) { dmrginp.makeopsT -> start(); built = true; allocate(b.get_braStateInfo(), b.get_ketStateInfo()); const int i = get_orbs()[0]; const int j = get_orbs()[1]; const int k = get_orbs()[2]; const int l = get_orbs()[3]; SpinBlock* leftBlock = b.get_leftBlock(); SpinBlock* rightBlock = b.get_rightBlock(); if (leftBlock->get_op_array(CRE_CRE_CRE_CRE).has(i,j,k,l)) { const boost::shared_ptr<SparseMatrix>& op = leftBlock->get_op_rep(CRE_CRE_CRE_CRE, quantum_ladder, i,j,k,l); if (rightBlock->get_sites().size() == 0) SpinAdapted::operatorfunctions::TensorTrace(leftBlock, *op, &b, &(b.get_stateInfo()), *this); dmrginp.makeopsT -> stop(); return; } assert(false && "Only build CRECRECRECRE in the starting block when spin-embeding is used"); }
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) }; } }
/* void SpinAdapted::operatorfunctions::TensorMultiply(const SpinBlock *ablock, const Baseoperator<Matrix>& a, const Baseoperator<Matrix>& b, const SpinBlock *cblock, Wavefunction& c, Wavefunction& v, const SpinQuantum opQ, double scale) { // can be used for situation with different bra and ket const int leftBraOpSz = cblock->get_leftBlock()->get_braStateInfo().quanta.size (); const int leftKetOpSz = cblock->get_leftBlock()->get_ketStateInfo().quanta.size (); const int rightBraOpSz = cblock->get_rightBlock()->get_braStateInfo().quanta.size (); const int rightKetOpSz = cblock->get_rightBlock()->get_ketStateInfo().quanta.size (); const StateInfo* lbraS = cblock->get_braStateInfo().leftStateInfo, *rbraS = cblock->get_braStateInfo().rightStateInfo; const StateInfo* lketS = cblock->get_ketStateInfo().leftStateInfo, *rketS = cblock->get_ketStateInfo().rightStateInfo; const char conjC = (cblock->get_leftBlock() == ablock) ? 'n' : 't'; const Baseoperator<Matrix>& leftOp = (conjC == 'n') ? a : b; // an ugly hack to support the release memory optimisation const Baseoperator<Matrix>& rightOp = (conjC == 'n') ? b : a; const char leftConj = (conjC == 'n') ? a.conjugacy() : b.conjugacy(); const char rightConj = (conjC == 'n') ? b.conjugacy() : a.conjugacy(); Wavefunction u; u.resize(leftBraOpSz*leftKetOpSz, rightKetOpSz); int totalmem =0; { for (int lQrQPrime = 0; lQrQPrime<leftBraOpSz*rightKetOpSz; ++lQrQPrime) { int rQPrime = lQrQPrime%rightKetOpSz, lQ = lQrQPrime/rightKetOpSz; for (int lQPrime = 0; lQPrime < leftKetOpSz; lQPrime++) if (leftOp.allowed(lQ, lQPrime) && c.allowed(lQPrime, rQPrime)) { int lindex = lQ*leftKetOpSz+lQPrime; u.allowed(lindex, rQPrime) = true; u(lindex,rQPrime).ReSize(lbraS->getquantastates(lQ), rketS->getquantastates(rQPrime)); double factor = leftOp.get_scaling(lbraS->quanta[lQ], lketS->quanta[lQPrime]); MatrixMultiply (leftOp.operator_element(lQ, lQPrime), leftConj, c.operator_element(lQPrime, rQPrime), 'n', u.operator_element(lindex, rQPrime), factor, 0.); } } } pout << "after first step in tensormultiply"<<endl; mcheck("before davidson but after all blocks are built"); { for (int lQrQ = 0; lQrQ<leftBraOpSz*rightBraOpSz; ++lQrQ) { int rQ = lQrQ%rightBraOpSz, lQ=lQrQ/rightBraOpSz; if (v.allowed(lQ, rQ)) for (int rQPrime = 0; rQPrime < rightKetOpSz; rQPrime++) if (rightOp.allowed(rQ, rQPrime)) for (int lQPrime = 0; lQPrime < leftKetOpSz; lQPrime++) if (leftOp.allowed(lQ, lQPrime) && u.allowed(lQ*leftKetOpSz+lQPrime, rQPrime)) { int lindex = lQ*leftKetOpSz+lQPrime; double factor = scale; factor *= dmrginp.get_ninej()(lketS->quanta[lQPrime].get_s().getirrep(), rketS->quanta[rQPrime].get_s().getirrep() , c.get_deltaQuantum(0).get_s().getirrep(), leftOp.get_spin().getirrep(), rightOp.get_spin().getirrep(), opQ.get_s().getirrep(), lbraS->quanta[lQ].get_s().getirrep(), rbraS->quanta[rQ].get_s().getirrep() , v.get_deltaQuantum(0).get_s().getirrep()); factor *= Symmetry::spatial_ninej(lketS->quanta[lQPrime].get_symm().getirrep() , rketS->quanta[rQPrime].get_symm().getirrep(), c.get_symm().getirrep(), leftOp.get_symm().getirrep(), rightOp.get_symm().getirrep(), opQ.get_symm().getirrep(), lbraS->quanta[lQ].get_symm().getirrep() , rbraS->quanta[rQ].get_symm().getirrep(), v.get_symm().getirrep()); int parity = rightOp.get_fermion() && IsFermion(lketS->quanta[lQPrime]) ? -1 : 1; factor *= rightOp.get_scaling(rbraS->quanta[rQ], rketS->quanta[rQPrime]); MatrixMultiply (u.operator_element(lindex, rQPrime), 'n', rightOp(rQ, rQPrime), TransposeOf(rightOp.conjugacy()), v.operator_element(lQ, rQ), factor*parity); } } } } */ void SpinAdapted::operatorfunctions::OperatorScaleAdd(double scaleV, const SpinBlock& b, const Baseoperator<Matrix>& op1, Baseoperator<Matrix>& op2) { const StateInfo& s = b.get_stateInfo(); for (int lQ = 0; lQ< op2.nrows(); lQ++) for (int rQ = 0; rQ<op2.ncols(); rQ++) if (op2.allowed(lQ, rQ) && op1.allowed(lQ,rQ)) { double factor = op1.get_scaling(s.quanta[lQ], s.quanta[rQ]); if (op1.conjugacy() == 't') MatrixScaleAdd(scaleV*factor, op1.operator_element(lQ,rQ).t(), op2.operator_element(lQ,rQ)); else MatrixScaleAdd(scaleV*factor, op1.operator_element(lQ,rQ), op2.operator_element(lQ,rQ)); } }
void SpinAdapted::InitBlocks::InitBigBlock(SpinBlock &leftBlock, SpinBlock &rightBlock, SpinBlock &big, const std::vector<SpinQuantum>& braquanta, const std::vector<SpinQuantum>& ketquanta) { //set big block components big.set_integralIndex() = leftBlock.get_integralIndex(); big.nonactive_orb() = leftBlock.nonactive_orb(); big.set_big_components(); // build the big block if (dmrginp.hamiltonian() == BCS) { if(braquanta.size()!=0) big.BuildSumBlock(SPIN_NUMBER_CONSTRAINT, leftBlock, rightBlock,braquanta,ketquanta); else big.BuildSumBlock(SPIN_NUMBER_CONSTRAINT, leftBlock, rightBlock); } else { if(braquanta.size()!=0) big.BuildSumBlock(PARTICLE_SPIN_NUMBER_CONSTRAINT, leftBlock, rightBlock,braquanta,ketquanta); else big.BuildSumBlock(PARTICLE_SPIN_NUMBER_CONSTRAINT, leftBlock, rightBlock); } }
void SparseMatrix::buildUsingCsf(const SpinBlock& b, vector< vector<Csf> >& ladders, std::vector< Csf >& s) { StateInfo stateinfo = b.get_stateInfo(); built = true; allocate(stateinfo); for (int i=0; i < stateinfo.quanta.size(); i++) for (int j=0; j<stateinfo.quanta.size(); j++) if (allowedQuantaMatrix(i,j) ) for (int jq =stateinfo.unBlockedIndex[j]; jq < stateinfo.unBlockedIndex[j]+stateinfo.quantaStates[j]; jq++) { for (int iq =stateinfo.unBlockedIndex[i]; iq < stateinfo.unBlockedIndex[i]+stateinfo.quantaStates[i]; iq++) operatorMatrix(i,j)(iq-stateinfo.unBlockedIndex[i]+1, jq-stateinfo.unBlockedIndex[j]+1) = redMatrixElement(s[iq], ladders[jq], &b); } }
void finish_tensor_product( SpinBlock& b, SpinBlock* sysdot, const SparseMatrix& sysdot_op1, const SparseMatrix& sysdot_op2, SparseMatrix& op, bool include_parity, std::string& build_pattern ) { // Build and store new operator assert( ! op.get_built() ); op.set_built() = true; op.set_build_pattern() = build_pattern; op.set_deltaQuantum(1, op.get_quantum_ladder().at( build_pattern ).at(2) ); op.allocate(b.get_stateInfo()); // Do tensor product double parity = 1.0; if ( include_parity ) parity = getCommuteParity( sysdot_op1.get_deltaQuantum(0), sysdot_op2.get_deltaQuantum(0), op.get_deltaQuantum(0) ); SpinAdapted::operatorfunctions::TensorProduct(sysdot, sysdot_op1, sysdot_op2, &b, &(b.get_stateInfo()), op, parity); }
void SpinBlock::store (bool forward, const vector<int>& sites, SpinBlock& b) { Timer disktimer; std::string file; if (forward) file = str(boost::format("%s%s%d%s%d%s%d%s") % dmrginp.save_prefix() % "/SpinBlock-forward-"% sites[0] % "-" % sites[sites.size()-1] % "." % mpigetrank() % ".tmp" ); else file = str(boost::format("%s%s%d%s%d%s%d%s") % dmrginp.save_prefix() % "/SpinBlock-backward-"% sites[0] % "-" % sites[sites.size()-1] % "." % mpigetrank() % ".tmp" ); if (dmrginp.outputlevel() > 0) pout << "\t\t\t Saving block file :: " << file << endl; std::ofstream ofs(file.c_str(), std::ios::binary); b.Save (ofs); ofs.close(); //pout << "\t\t\t block save disk time " << disktimer.elapsedwalltime() << " " << disktimer.elapsedcputime() << endl; }
void SparseMatrix::allocate(const SpinBlock& b) { allocate(b.get_stateInfo()); }
void SpinAdapted::InitBlocks::InitNewEnvironmentBlock(SpinBlock &environment, SpinBlock& environmentDot, SpinBlock &newEnvironment, const SpinBlock &system, SpinBlock &systemDot, int leftState, int rightState, const int &sys_add, const int &env_add, const bool &forward, const bool &direct, const bool &onedot, const bool &nexact, const bool &useSlater, int integralIndex, bool haveNormops, bool haveCompops, const bool& dot_with_sys, int constraint, const std::vector<SpinQuantum>& braquanta, const std::vector<SpinQuantum>& ketquanta) { // now initialise environment Dot int systemDotStart, systemDotEnd, environmentDotStart, environmentDotEnd, environmentStart, environmentEnd; int systemDotSize = sys_add - 1; int environmentDotSize = env_add - 1; if (forward) { systemDotStart = dmrginp.spinAdapted() ? *system.get_sites().rbegin () + 1 : (*system.get_sites().rbegin ())/2 + 1 ; systemDotEnd = systemDotStart + systemDotSize; environmentDotStart = systemDotEnd + 1; environmentDotEnd = environmentDotStart + environmentDotSize; environmentStart = environmentDotEnd + 1; environmentEnd = dmrginp.spinAdapted() ? dmrginp.last_site() - 1 : dmrginp.last_site()/2 - 1; } else { systemDotStart = dmrginp.spinAdapted() ? system.get_sites()[0] - 1 : (system.get_sites()[0])/2 - 1 ; systemDotEnd = systemDotStart - systemDotSize; environmentDotStart = systemDotEnd - 1; environmentDotEnd = environmentDotStart - environmentDotSize; environmentStart = environmentDotEnd - 1; environmentEnd = 0; } std::vector<int> environmentSites; environmentSites.resize(abs(environmentEnd - environmentStart) + 1); for (int i = 0; i < abs(environmentEnd - environmentStart) + 1; ++i) *(environmentSites.begin () + i) = min(environmentStart,environmentEnd) + i; // now initialise environment if (useSlater) { // for FCI StateInfo system_stateinfo = system.get_stateInfo(); StateInfo sysdot_stateinfo = systemDot.get_stateInfo(); StateInfo tmp; TensorProduct (system_stateinfo, sysdot_stateinfo, tmp, NO_PARTICLE_SPIN_NUMBER_CONSTRAINT); // tmp has the system+dot quantum numbers tmp.CollectQuanta (); // exact environment if (dmrginp.do_fci() || environmentSites.size() == nexact) { if ((!dot_with_sys && onedot) || !onedot) { // environment has dot environment.set_integralIndex() = integralIndex; environment.default_op_components(!forward, leftState==rightState); environment.setstoragetype(DISTRIBUTED_STORAGE); environment.BuildTensorProductBlock(environmentSites); // exact block SpinBlock::store (true, environmentSites, environment, leftState, rightState); } else { // environment has no dot, so newEnv = Env newEnvironment.set_integralIndex() = integralIndex; newEnvironment.default_op_components(!forward, leftState==rightState); newEnvironment.setstoragetype(DISTRIBUTED_STORAGE); newEnvironment.BuildTensorProductBlock(environmentSites); SpinBlock::store (true, environmentSites, newEnvironment, leftState, rightState); } } else if (dmrginp.warmup() == LOCAL2 || dmrginp.warmup() == LOCAL3 || dmrginp.warmup() == LOCAL4) { int nactiveSites, ncoreSites; if (dmrginp.warmup() == LOCAL2) { nactiveSites = 1; } else if (dmrginp.warmup() == LOCAL3) { nactiveSites = 2; } else if (dmrginp.warmup() == LOCAL4) { nactiveSites = 3; } if (dot_with_sys && onedot) { nactiveSites += 1; } if (nactiveSites > environmentSites.size()) { nactiveSites = environmentSites.size(); } ncoreSites = environmentSites.size() - nactiveSites; // figure out what sites are in the active and core sites int environmentActiveEnd = forward ? environmentStart + nactiveSites - 1 : environmentStart - nactiveSites + 1; int environmentCoreStart = forward ? environmentActiveEnd + 1 : environmentActiveEnd - 1; std::vector<int> activeSites(nactiveSites), coreSites(ncoreSites); for (int i = 0; i < nactiveSites; ++i) { activeSites[i] = min(environmentStart,environmentActiveEnd) + i; } for (int i = 0; i < ncoreSites; ++i) { coreSites[i] = min(environmentCoreStart,environmentEnd) + i; } SpinBlock environmentActive, environmentCore; environmentActive.nonactive_orb() = system.nonactive_orb(); environmentCore.nonactive_orb() = system.nonactive_orb(); if (coreSites.size() > 0) { environmentActive.set_integralIndex() = integralIndex; environmentCore.set_integralIndex() = integralIndex; environmentActive.default_op_components(!forward, leftState==rightState); environmentActive.setstoragetype(DISTRIBUTED_STORAGE); environmentCore.default_op_components(!forward, leftState==rightState); environmentCore.setstoragetype(DISTRIBUTED_STORAGE); environmentActive.BuildTensorProductBlock(activeSites); environmentCore.BuildSingleSlaterBlock(coreSites); dmrginp.datatransfer -> start(); environmentCore.addAdditionalCompOps(); environmentActive.addAdditionalCompOps(); dmrginp.datatransfer -> stop(); if ((!dot_with_sys && onedot) || !onedot) { environment.set_integralIndex() = integralIndex; environment.default_op_components(!forward, leftState == rightState); environment.setstoragetype(DISTRIBUTED_STORAGE); environment.BuildSumBlock(constraint, environmentCore, environmentActive,braquanta,ketquanta); } else { newEnvironment.set_integralIndex() = integralIndex; newEnvironment.default_op_components(direct, environmentCore, environmentActive, haveNormops, haveCompops, leftState == rightState); newEnvironment.setstoragetype(DISTRIBUTED_STORAGE); newEnvironment.BuildSumBlock(constraint, environmentCore, environmentActive,braquanta,ketquanta); if (dmrginp.outputlevel() > 0) { pout << "\t\t\t NewEnvironment block " << endl << newEnvironment << endl; newEnvironment.printOperatorSummary(); } } } else { // no core if ((!dot_with_sys && onedot) || !onedot) { environment.set_integralIndex() = integralIndex; environment.default_op_components(!forward, leftState==rightState); environment.setstoragetype(DISTRIBUTED_STORAGE); environment.BuildTensorProductBlock(environmentSites); // exact block } else { newEnvironment.set_integralIndex() = integralIndex; newEnvironment.default_op_components(!forward, leftState==rightState); newEnvironment.setstoragetype(DISTRIBUTED_STORAGE); newEnvironment.BuildTensorProductBlock(environmentSites); } } } else { //used for warmup guess environemnt std::vector<SpinQuantum> quantumNumbers; std::vector<int> distribution; std::map<SpinQuantum, int> quantaDist; std::map<SpinQuantum, int>::iterator quantaIterator; bool environmentComplementary = !forward; StateInfo tmp2; // tmp is the quantum numbers of newSystem (sys + sysdot) if (onedot) tmp.quanta_distribution (quantumNumbers, distribution, true); else { StateInfo environmentdot_stateinfo = environmentDot.get_stateInfo(); TensorProduct (tmp, environmentdot_stateinfo, tmp2, constraint); tmp2.CollectQuanta (); tmp2.quanta_distribution (quantumNumbers, distribution, true); } for (int i = 0; i < distribution.size (); ++i) { quantaIterator = quantaDist.find(quantumNumbers[i]); if (quantaIterator != quantaDist.end()) distribution[i] += quantaIterator->second; distribution [i] /= 4; distribution [i] += 1; if (distribution [i] > dmrginp.nquanta()) distribution [i] = dmrginp.nquanta(); if(quantaIterator != quantaDist.end()) { quantaIterator->second = distribution[i]; } else { quantaDist[quantumNumbers[i]] = distribution[i]; } } if (dmrginp.outputlevel() > 0) pout << "\t\t\t Quantum numbers and states used for warm up :: " << endl << "\t\t\t "; quantumNumbers.clear(); quantumNumbers.reserve(distribution.size()); distribution.clear();distribution.reserve(quantumNumbers.size()); std::map<SpinQuantum, int>::iterator qit = quantaDist.begin(); for (; qit != quantaDist.end(); qit++) { quantumNumbers.push_back( qit->first); distribution.push_back(qit->second); if (dmrginp.outputlevel() > 0) { pout << quantumNumbers.back() << " = " << distribution.back() << ", "; if (! (quantumNumbers.size() - 6) % 6) pout << endl << "\t\t\t "; } } pout << endl; if(dot_with_sys && onedot) { newEnvironment.set_integralIndex() = integralIndex; newEnvironment.BuildSlaterBlock (environmentSites, quantumNumbers, distribution, false, false); } else { environment.set_integralIndex() = integralIndex; environment.BuildSlaterBlock (environmentSites, quantumNumbers, distribution, false, haveNormops); } } } else { if (dmrginp.outputlevel() > 0) pout << "\t\t\t Restoring block of size " << environmentSites.size () << " from previous iteration" << endl; if(dot_with_sys && onedot) { newEnvironment.set_integralIndex() = integralIndex; SpinBlock::restore (!forward, environmentSites, newEnvironment, leftState, rightState); } else { environment.set_integralIndex() = integralIndex; SpinBlock::restore (!forward, environmentSites, environment, leftState, rightState); } if (dmrginp.outputlevel() > 0) mcheck(""); } // now initialise newEnvironment if (!dot_with_sys || !onedot) { dmrginp.datatransfer -> start(); environment.addAdditionalCompOps(); dmrginp.datatransfer -> stop(); newEnvironment.set_integralIndex() = integralIndex; newEnvironment.default_op_components(direct, environment, environmentDot, haveNormops, haveCompops, leftState==rightState); newEnvironment.setstoragetype(DISTRIBUTED_STORAGE); newEnvironment.BuildSumBlock (constraint, environment, environmentDot,braquanta,ketquanta); if (dmrginp.outputlevel() > -1) { pout << "\t\t\t Environment block " << endl << environment << endl; environment.printOperatorSummary(); pout << "\t\t\t NewEnvironment block " << endl << newEnvironment << endl; newEnvironment.printOperatorSummary(); } } else if (dmrginp.outputlevel() > 0) { pout << "\t\t\t Environment block " << endl << newEnvironment << endl; newEnvironment.printOperatorSummary(); } }
void do_3index_1_2_tensor_products( bool forwards, const opTypes& optype, const opTypes& rhsType, const opTypes& lhsType, SpinBlock& big, SpinBlock* rhsBlock, SpinBlock* lhsBlock, std::ofstream& ofs, const std::vector<Matrix>& rotateMatrix, const StateInfo *stateinfo ) { // (i | j,k ) partition //------------------------- Op_component_base& rhs_array = rhsBlock->get_op_array(rhsType); Op_component_base& lhs_array = lhsBlock->get_op_array(lhsType); assert ( (rhs_array.get_size() == 1) || (lhs_array.get_size() == 1) ); //pout << "tensor_1_2: rhs_size = " << rhs_array.get_size() << "; op = " << rhs_array.get_op_string() << endl; //pout << "tensor_1_2: lhs_size = " << lhs_array.get_size() << "; op = " << lhs_array.get_op_string() << endl; // Initialize filesystem std::ifstream lhsifs; if (( ! dmrginp.do_npdm_in_core()) && lhsBlock->size() > 1) lhsifs.open( lhs_array.get_filename().c_str(), std::ios::binary ); // Loop over all lhs operator indices for (int idx = 0; idx < lhs_array.get_size(); ++idx) { std::vector<boost::shared_ptr<SparseMatrix> > lhs_ops; // Assume 2-index operators are available on this processor in core lhs_ops = lhs_array.get_local_element(idx); // Loop over all rhs operator indices for (int iidx = 0; iidx < rhs_array.get_size(); ++iidx) { std::vector<boost::shared_ptr<SparseMatrix> > rhs_ops = rhs_array.get_local_element(iidx); int i = rhs_ops[0]->get_orbs()[0]; int j = lhs_ops[0]->get_orbs()[0]; int k = lhs_ops[0]->get_orbs()[1]; //pout << "i = " << i << endl; //pout << "j,k = " << j << "," << k << endl; // In parallel calculations not all operators are built on each proc if ( ! big.get_op_array(optype).has_local_index(i,j,k) ) continue; //pout << "building i,j,k = " << i << "," << j << "," << k << endl; std::vector<boost::shared_ptr<SparseMatrix> > vec = big.get_op_array(optype).get_element(i,j,k); //pout << "got i,j,k\n"; // Loop over lhs spin-op components for (int jdx=0; jdx < lhs_ops.size(); jdx++) { boost::shared_ptr<SparseMatrix>& lhs_op = lhs_ops[jdx]; assert( lhs_op->get_built() ); std::string build_23 = lhs_op->get_build_pattern(); //pout << build_23 << endl; //pout << "getting spin_23\n"; std::vector<SpinQuantum> spin_23 = lhs_op->get_quantum_ladder().at(build_23); //pout << "got spin_23\n"; // Loop over rhs spin-op components for (int jjdx=0; jjdx < rhs_ops.size(); jjdx++) { boost::shared_ptr<SparseMatrix>& rhs_op = rhs_ops[jjdx]; assert( rhs_op->get_built() ); std::string build_1 = rhs_op->get_build_pattern(); std::string build_pattern = "(" + build_1 + build_23 + ")"; // Allocate and build new operator for (int sx=0; sx < vec.size(); sx++) { boost::shared_ptr<SparseMatrix>& op = vec[sx]; // Select relevant spin component std::vector<SpinQuantum> s = { op->get_quantum_ladder().at(build_pattern).at(0) }; if ( s == spin_23 ) { finish_tensor_product( big, rhsBlock, *rhs_op, *lhs_op, *op, forwards, build_pattern ); // Renormalise operator op->renormalise_transform( rotateMatrix, stateinfo ); } } } } // Store spin-batch on disk if ( ! dmrginp.do_npdm_in_core() ) store_ops_on_disk( ofs, vec ); } } if ( lhsifs.is_open() ) lhsifs.close(); }
double SweepTwopdm::do_one(SweepParams &sweepParams, const bool &warmUp, const bool &forward, const bool &restart, const int &restartSize, int state) { Timer sweeptimer; int integralIndex = 0; if (dmrginp.hamiltonian() == BCS) { pout << "Two PDM with BCS calculations is not implemented" << endl; exit(0); } pout.precision(12); SpinBlock system; const int nroots = dmrginp.nroots(); std::vector<double> finalEnergy(nroots,0.); std::vector<double> finalEnergy_spins(nroots,0.); double finalError = 0.; sweepParams.set_sweep_parameters(); // a new renormalisation sweep routine pout << ((forward) ? "\t\t\t Starting renormalisation sweep in forwards direction" : "\t\t\t Starting renormalisation sweep in backwards direction") << endl; pout << "\t\t\t ============================================================================ " << endl; InitBlocks::InitStartingBlock (system,forward, sweepParams.current_root(), sweepParams.current_root(), sweepParams.get_forward_starting_size(), sweepParams.get_backward_starting_size(), restartSize, restart, warmUp, integralIndex); if(!restart) sweepParams.set_block_iter() = 0; pout << "\t\t\t Starting block is :: " << endl << system << endl; if (!restart) SpinBlock::store (forward, system.get_sites(), system, sweepParams.current_root(), sweepParams.current_root()); // if restart, just restoring an existing block -- sweepParams.savestate(forward, system.get_sites().size()); bool dot_with_sys = true; array_4d<double> twopdm(2*dmrginp.last_site(), 2*dmrginp.last_site(), 2*dmrginp.last_site(), 2*dmrginp.last_site()); twopdm.Clear(); save_twopdm_binary(twopdm, state, state); for (; sweepParams.get_block_iter() < sweepParams.get_n_iters(); ) { pout << "\n\t\t\t Block Iteration :: " << sweepParams.get_block_iter() << endl; pout << "\t\t\t ----------------------------" << endl; if (forward) p1out << "\t\t\t Current direction is :: Forwards " << endl; else p1out << "\t\t\t Current direction is :: Backwards " << endl; //if (SHOW_MORE) pout << "system block" << endl << system << endl; if (dmrginp.no_transform()) sweepParams.set_guesstype() = BASIC; else if (!warmUp && sweepParams.get_block_iter() != 0) sweepParams.set_guesstype() = TRANSFORM; else if (!warmUp && sweepParams.get_block_iter() == 0 && ((dmrginp.algorithm_method() == TWODOT_TO_ONEDOT && dmrginp.twodot_to_onedot_iter() != sweepParams.get_sweep_iter()) || dmrginp.algorithm_method() != TWODOT_TO_ONEDOT)) sweepParams.set_guesstype() = TRANSPOSE; else sweepParams.set_guesstype() = BASIC; p1out << "\t\t\t Blocking and Decimating " << endl; SpinBlock newSystem; BlockAndDecimate (sweepParams, system, newSystem, warmUp, dot_with_sys, state); for(int j=0;j<nroots;++j) pout << "\t\t\t Total block energy for State [ " << j << " ] with " << sweepParams.get_keep_states()<<" :: " << sweepParams.get_lowest_energy()[j] <<endl; finalEnergy_spins = ((sweepParams.get_lowest_energy()[0] < finalEnergy[0]) ? sweepParams.get_lowest_energy_spins() : finalEnergy_spins); finalEnergy = ((sweepParams.get_lowest_energy()[0] < finalEnergy[0]) ? sweepParams.get_lowest_energy() : finalEnergy); finalError = max(sweepParams.get_lowest_error(),finalError); system = newSystem; pout << system<<endl; SpinBlock::store (forward, system.get_sites(), system, sweepParams.current_root(), sweepParams.current_root()); p1out << "\t\t\t saving state " << system.get_sites().size() << endl; ++sweepParams.set_block_iter(); //sweepParams.savestate(forward, system.get_sites().size()); } //for(int j=0;j<nroots;++j) {int j = state; pout << "\t\t\t Finished Sweep with " << sweepParams.get_keep_states() << " states and sweep energy for State [ " << j << " ] with Spin [ " << dmrginp.molecule_quantum().get_s() << " ] :: " << finalEnergy[j] << endl; } pout << "\t\t\t Largest Error for Sweep with " << sweepParams.get_keep_states() << " states is " << finalError << endl; pout << "\t\t\t ============================================================================ " << endl; int i = state, j = state; //for (int j=0; j<=i; j++) { load_twopdm_binary(twopdm, i, j); //calcenergy(twopdm, i); save_twopdm_text(twopdm, i, j); save_spatial_twopdm_text(twopdm, i, j); save_spatial_twopdm_binary(twopdm, i, j); // update the static number of iterations ++sweepParams.set_sweep_iter(); ecpu = sweeptimer.elapsedcputime(); ewall = sweeptimer.elapsedwalltime(); pout << "\t\t\t Elapsed Sweep CPU Time (seconds): " << setprecision(3) << ecpu << endl; pout << "\t\t\t Elapsed Sweep Wall Time (seconds): " << setprecision(3) << ewall << endl; return finalEnergy[0]; }
void SpinAdapted::InitBlocks::InitNewOverlapEnvironmentBlock(SpinBlock &environment, SpinBlock& environmentDot, SpinBlock &newEnvironment, const SpinBlock &system, SpinBlock &systemDot, int leftState, int rightState, const int &sys_add, const int &env_add, const bool &forward, int integralIndex, const bool &onedot, const bool& dot_with_sys, int constraint) { // now initialise environment Dot int systemDotStart, systemDotEnd, environmentDotStart, environmentDotEnd, environmentStart, environmentEnd; int systemDotSize = sys_add - 1; int environmentDotSize = env_add - 1; if (forward) { systemDotStart = dmrginp.spinAdapted() ? *system.get_sites().rbegin () + 1 : (*system.get_sites().rbegin ())/2 + 1 ; systemDotEnd = systemDotStart + systemDotSize; environmentDotStart = systemDotEnd + 1; environmentDotEnd = environmentDotStart + environmentDotSize; environmentStart = environmentDotEnd + 1; environmentEnd = dmrginp.spinAdapted() ? dmrginp.last_site() - 1 : dmrginp.last_site()/2 - 1; } else { systemDotStart = dmrginp.spinAdapted() ? system.get_sites()[0] - 1 : (system.get_sites()[0])/2 - 1 ; systemDotEnd = systemDotStart - systemDotSize; environmentDotStart = systemDotEnd - 1; environmentDotEnd = environmentDotStart - environmentDotSize; environmentStart = environmentDotEnd - 1; environmentEnd = 0; } std::vector<int> environmentSites; environmentSites.resize(abs(environmentEnd - environmentStart) + 1); for (int i = 0; i < abs(environmentEnd - environmentStart) + 1; ++i) *(environmentSites.begin () + i) = min(environmentStart,environmentEnd) + i; p2out << "\t\t\t Restoring block of size " << environmentSites.size () << " from previous iteration" << endl; if(dot_with_sys && onedot) { newEnvironment.set_integralIndex() = integralIndex; SpinBlock::restore (!forward, environmentSites, newEnvironment, leftState, rightState); } else { environment.set_integralIndex() = integralIndex; SpinBlock::restore (!forward, environmentSites, environment, leftState, rightState); } if (dmrginp.outputlevel() > 0) mcheck(""); // now initialise newEnvironment if (!dot_with_sys || !onedot) { newEnvironment.set_integralIndex() = integralIndex; newEnvironment.initialise_op_array(OVERLAP, false); //newEnvironment.set_op_array(OVERLAP) = boost::shared_ptr<Op_component<Overlap> >(new Op_component<Overlap>(false)); newEnvironment.setstoragetype(DISTRIBUTED_STORAGE); newEnvironment.BuildSumBlock (constraint, environment, environmentDot); p2out << "\t\t\t Environment block " << endl << environment << endl; environment.printOperatorSummary(); p2out << "\t\t\t NewEnvironment block " << endl << newEnvironment << endl; newEnvironment.printOperatorSummary(); } else { p2out << "\t\t\t Environment block " << endl << newEnvironment << endl; newEnvironment.printOperatorSummary(); } }
void SweepOnepdm::BlockAndDecimate (SweepParams &sweepParams, SpinBlock& system, SpinBlock& newSystem, const bool &useSlater, const bool& dot_with_sys) { //mcheck("at the start of block and decimate"); // figure out if we are going forward or backwards dmrginp.guessgenT -> start(); bool forward = (system.get_sites() [0] == 0); SpinBlock systemDot; SpinBlock envDot; int systemDotStart, systemDotEnd; int systemDotSize = sweepParams.get_sys_add() - 1; if (forward) { systemDotStart = *system.get_sites().rbegin () + 1; systemDotEnd = systemDotStart + systemDotSize; } else { systemDotStart = system.get_sites() [0] - 1; systemDotEnd = systemDotStart - systemDotSize; } vector<int> spindotsites(2); spindotsites[0] = systemDotStart; spindotsites[1] = systemDotEnd; systemDot = SpinBlock(systemDotStart, systemDotEnd); SpinBlock environment, environmentDot, newEnvironment; int environmentDotStart, environmentDotEnd, environmentStart, environmentEnd; const int nexact = forward ? sweepParams.get_forward_starting_size() : sweepParams.get_backward_starting_size(); system.addAdditionalCompOps(); InitBlocks::InitNewSystemBlock(system, systemDot, newSystem, sweepParams.get_sys_add(), dmrginp.direct(), DISTRIBUTED_STORAGE, true, true); InitBlocks::InitNewEnvironmentBlock(environment, systemDot, newEnvironment, system, systemDot, sweepParams.get_sys_add(), sweepParams.get_env_add(), forward, dmrginp.direct(), sweepParams.get_onedot(), nexact, useSlater, true, true, true); SpinBlock big; newSystem.set_loopblock(true); system.set_loopblock(false); newEnvironment.set_loopblock(false); InitBlocks::InitBigBlock(newSystem, newEnvironment, big); const int nroots = dmrginp.nroots(); std::vector<Wavefunction> solutions(nroots); for(int i=0;i<nroots;++i) { StateInfo newInfo; solutions[i].LoadWavefunctionInfo (newInfo, newSystem.get_sites(), i); } #ifndef SERIAL mpi::communicator world; mpi::broadcast(world,solutions,0); #endif #ifdef SERIAL const int numprocs = 1; #endif #ifndef SERIAL const int numprocs = world.size(); #endif compute_onepdm(solutions, system, systemDot, newSystem, newEnvironment, big, numprocs); }
void SpinAdapted::mps_nevpt::type1::Startup(const SweepParams &sweepParams, const bool &forward, perturber& pb, int baseState) { #ifndef SERIAL mpi::communicator world; #endif assert(forward); SpinBlock system; system.nonactive_orb() =pb.orb(); bool restart=false, warmUp = false; int forward_starting_size=1, backward_starting_size=0, restartSize =0; InitBlocks::InitStartingBlock(system, forward, pb.wavenumber(), baseState, forward_starting_size, backward_starting_size, restartSize, restart, warmUp, 0,pb.braquanta, pb.ketquanta); SpinBlock::store (forward, system.get_sites(), system, pb.wavenumber(), baseState); // if restart, just restoring an existing block -- for (int i=0; i<mps_nevpt::sweepIters; i++) { SpinBlock newSystem; SpinBlock dotSystem(i+1,i+1,pb.orb(),false); system.addAdditionalCompOps(); //newSystem.default_op_components(true, system, dotSystem, true, true, false); newSystem.perturb_op_components(false, system, dotSystem, pb); newSystem.setstoragetype(DISTRIBUTED_STORAGE); newSystem.BuildSumBlock(LessThanQ, system, dotSystem, pb.braquanta, pb.ketquanta); newSystem.printOperatorSummary(); //SpinBlock Environment, big; //SpinBlock::restore (!forward, newSystem.get_complementary_sites() , Environment, baseState, baseState); //TODO //SpinBlock::restore (!forward, newSystem.get_complementary_sites() , Environment,sweepParams.current_root(),sweepParams.current_root()); //big.BuildSumBlock(PARTICLE_SPIN_NUMBER_CONSTRAINT, newSystem, Environment, pb.braquanta, pb.ketquanta); //StateInfo envStateInfo; StateInfo ketStateInfo; StateInfo braStateInfo; StateInfo halfbraStateInfo;// It has the same left and right StateInfo as braStateInfo. However, its total quanta is pb.ketquanta. // It is used to project solution into to braStateInfo. std::vector<Wavefunction> solution; solution.resize(1); std::vector<Wavefunction> outputState; outputState.resize(1); std::vector<Wavefunction> solutionprojector; solutionprojector.resize(1); solution[0].LoadWavefunctionInfo(ketStateInfo, newSystem.get_sites(), baseState); #ifndef SERIAL broadcast(world, ketStateInfo, 0); broadcast(world, solution, 0); #endif outputState[0].AllowQuantaFor(newSystem.get_braStateInfo(), *(ketStateInfo.rightStateInfo), pb.braquanta); outputState[0].set_onedot(solution[0].get_onedot()); outputState[0].Clear(); solutionprojector[0].AllowQuantaFor(newSystem.get_braStateInfo(), *(ketStateInfo.rightStateInfo), pb.ketquanta); solutionprojector[0].set_onedot(solution[0].get_onedot()); solutionprojector[0].Clear(); //TensorProduct (newSystem.get_braStateInfo(), *(ketStateInfo.rightStateInfo), pb.braquanta[0], EqualQ, braStateInfo); //TODO //TensorProduct do not support const StateInfo& TensorProduct (newSystem.set_braStateInfo(), *(ketStateInfo.rightStateInfo), pb.braquanta[0], EqualQ, braStateInfo); TensorProduct (newSystem.set_braStateInfo(), *(ketStateInfo.rightStateInfo), pb.ketquanta[0], EqualQ, halfbraStateInfo); //StateInfo::restore(forward, environmentsites, envStateInfo, baseState); //DiagonalMatrix e; //if(i == 0) // GuessWave::guess_wavefunctions(solution, e, big, TRANSPOSE, true, true, 0.0, baseState); //else // GuessWave::guess_wavefunctions(solution, e, big, TRANSFORM, true, true, 0.0, baseState); //SpinAdapted::operatorfunctions::Product(&newSystem, ccd, solution[0], &ketStateInfo, stateb.getw(), temp, SpinQuantum(0, SpinSpace(0), IrrepSpace(0)), true, 1.0); boost::shared_ptr<SparseMatrix> O; if (pb.type() == TwoPerturbType::Va) O = newSystem.get_op_array(CDD_SUM).get_local_element(0)[0]->getworkingrepresentation(&newSystem); if (pb.type() == TwoPerturbType::Vi) O = newSystem.get_op_array(CCD_SUM).get_local_element(0)[0]->getworkingrepresentation(&newSystem); boost::shared_ptr<SparseMatrix> overlap = newSystem.get_op_array(OVERLAP).get_local_element(0)[0]->getworkingrepresentation(&newSystem); SpinAdapted::operatorfunctions::TensorMultiply(*O, &braStateInfo, &ketStateInfo , solution[0], outputState[0], pb.delta, true, 1.0); SpinAdapted::operatorfunctions::TensorMultiply(*overlap, &halfbraStateInfo, &ketStateInfo , solution[0], solutionprojector[0], overlap->get_deltaQuantum(0), true, 1.0); DensityMatrix bratracedMatrix(newSystem.get_braStateInfo()); bratracedMatrix.allocate(newSystem.get_braStateInfo()); double norm = DotProduct(outputState[0], outputState[0]); if(norm > NUMERICAL_ZERO) SpinAdapted::operatorfunctions::MultiplyProduct(outputState[0], Transpose(const_cast<Wavefunction&> (outputState[0])), bratracedMatrix, 0.5/norm); SpinAdapted::operatorfunctions::MultiplyProduct(solutionprojector[0], Transpose(const_cast<Wavefunction&> (solutionprojector[0])), bratracedMatrix, 0.5); std::vector<Matrix> brarotateMatrix, ketrotateMatrix; LoadRotationMatrix (newSystem.get_sites(), ketrotateMatrix, baseState); double error; if (!mpigetrank()) error = makeRotateMatrix(bratracedMatrix, brarotateMatrix, sweepParams.get_keep_states(), sweepParams.get_keep_qstates()); #ifndef SERIAL broadcast(world, ketrotateMatrix, 0); broadcast(world, brarotateMatrix, 0); #endif SaveRotationMatrix (newSystem.get_sites(), brarotateMatrix, pb.wavenumber()); newSystem.transform_operators(brarotateMatrix,ketrotateMatrix); SpinBlock::store (forward, newSystem.get_sites(), newSystem, pb.wavenumber(), baseState); // if restart, just restoring an existing block -- system=newSystem; } //TODO //It seems that there is no need to do Last Step of Sweep. }
void SpinAdapted::InitBlocks::InitStartingBlock (SpinBlock& startingBlock, const bool &forward, int leftState, int rightState, const int & forward_starting_size, const int &backward_starting_size, const int& restartSize, const bool &restart, const bool& warmUp, int integralIndex, const vector<SpinQuantum>& braquanta, const vector<SpinQuantum>& ketquanta) { if (restart && restartSize != 1) { int len = restart? restartSize : forward_starting_size; vector<int> sites(len); if (forward) for (int i=0; i<len; i++) sites[i] = i; else for (int i=0; i<len; i++) sites[i] = dmrginp.last_site() - len +i ; if (restart) SpinBlock::restore (forward, sites, startingBlock, leftState, rightState); else SpinBlock::restore (true, sites, startingBlock, leftState, rightState); } else if (forward) { if(startingBlock.nonactive_orb().size()!=0) startingBlock = SpinBlock(0, forward_starting_size - 1,startingBlock.nonactive_orb() , true); else startingBlock = SpinBlock(0, forward_starting_size - 1, integralIndex, leftState==rightState, true); if (dmrginp.add_noninteracting_orbs() && dmrginp.molecule_quantum().get_s().getirrep() != 0 && dmrginp.spinAdapted()) { SpinQuantum s = dmrginp.molecule_quantum(); s = SpinQuantum(s.get_s().getirrep(), s.get_s(), IrrepSpace(0)); int qs = 1, ns = 1; StateInfo addstate(ns, &s, &qs); SpinBlock dummyblock(addstate, integralIndex); SpinBlock newstartingBlock; newstartingBlock.set_integralIndex() = integralIndex; newstartingBlock.default_op_components(false, startingBlock, dummyblock, true, true, leftState==rightState); newstartingBlock.setstoragetype(LOCAL_STORAGE); if( braquanta.size()!= 0) newstartingBlock.BuildSumBlock(NO_PARTICLE_SPIN_NUMBER_CONSTRAINT, startingBlock, dummyblock,braquanta,ketquanta); else newstartingBlock.BuildSumBlock(NO_PARTICLE_SPIN_NUMBER_CONSTRAINT, startingBlock, dummyblock); startingBlock.clear(); startingBlock = newstartingBlock; } } else { std::vector<int> backwardSites; if(dmrginp.spinAdapted()) { for (int i = 0; i < backward_starting_size; ++i) backwardSites.push_back (dmrginp.last_site() - i - 1); } else { for (int i = 0; i < backward_starting_size; ++i) backwardSites.push_back (dmrginp.last_site()/2 - i - 1); } sort (backwardSites.begin (), backwardSites.end ()); startingBlock.set_integralIndex() = integralIndex; startingBlock.default_op_components(false, leftState==rightState); startingBlock.BuildTensorProductBlock (backwardSites); } }
//before you start optimizing each state you want to initalize all the overlap matrices void Sweep::InitializeOverlapSpinBlocks(SweepParams &sweepParams, const bool &forward, int stateA, int stateB) { SpinBlock system; sweepParams.set_sweep_parameters(); if (forward) pout << "\t\t\t Starting sweep "<< sweepParams.set_sweep_iter()<<" in forwards direction"<<endl; else pout << "\t\t\t Starting sweep "<< sweepParams.set_sweep_iter()<<" in backwards direction" << endl; pout << "\t\t\t ============================================================================ " << endl; int restartSize = 0; bool restart = false, warmUp = false; InitBlocks::InitStartingBlock (system,forward, stateA, stateB, sweepParams.get_forward_starting_size(), sweepParams.get_backward_starting_size(), restartSize, restart, warmUp); sweepParams.set_block_iter() = 0; if (dmrginp.outputlevel() > 0) pout << "\t\t\t Starting block is :: " << endl << system << endl; SpinBlock::store (forward, system.get_sites(), system, stateA, stateB); // if restart, just restoring an existing block -- sweepParams.savestate(forward, system.get_sites().size()); bool dot_with_sys = true; vector<int> syssites = system.get_sites(); if (dmrginp.outputlevel() > 0) mcheck("at the very start of sweep"); // just timer for (; sweepParams.get_block_iter() < sweepParams.get_n_iters(); ) // get_n_iters() returns the number of blocking iterations needed in one sweep { pout << "\t\t\t Block Iteration :: " << sweepParams.get_block_iter() << endl; pout << "\t\t\t ----------------------------" << endl; if (dmrginp.outputlevel() > 0) { if (forward) pout << "\t\t\t Current direction is :: Forwards " << endl; else pout << "\t\t\t Current direction is :: Backwards " << endl; } SpinBlock systemDot, environmentDot; int systemDotStart, systemDotEnd; int systemDotSize = sweepParams.get_sys_add() - 1; if (forward) { systemDotStart = dmrginp.spinAdapted() ? *system.get_sites().rbegin () + 1 : (*system.get_sites().rbegin ())/2 + 1 ; systemDotEnd = systemDotStart + systemDotSize; } else { systemDotStart = dmrginp.spinAdapted() ? system.get_sites()[0] - 1 : (system.get_sites()[0])/2 - 1 ; systemDotEnd = systemDotStart - systemDotSize; } systemDot = SpinBlock(systemDotStart, systemDotEnd, true); SpinBlock newSystem; // new system after blocking and decimating newSystem.initialise_op_array(OVERLAP, false); newSystem.setstoragetype(DISTRIBUTED_STORAGE); newSystem.BuildSumBlock (NO_PARTICLE_SPIN_NUMBER_CONSTRAINT, system, systemDot); std::vector<Matrix> brarotateMatrix, ketrotateMatrix; LoadRotationMatrix(newSystem.get_sites(), brarotateMatrix, stateA); LoadRotationMatrix(newSystem.get_sites(), ketrotateMatrix, stateB); newSystem.transform_operators(brarotateMatrix, ketrotateMatrix); system = newSystem; if (dmrginp.outputlevel() > 0){ pout << system<<endl; } SpinBlock::store (forward, system.get_sites(), system, stateA, stateB); ++sweepParams.set_block_iter(); sweepParams.savestate(forward, syssites.size()); if (dmrginp.outputlevel() > 0) mcheck("at the end of sweep iteration"); } pout << "\t\t\t ============================================================================ " << endl; // update the static number of iterations return ; }
void do_4index_3_1_tensor_products( bool forwards, const opTypes& optype, const opTypes& rhsType, const opTypes& lhsType, SpinBlock& big, SpinBlock* rhsBlock, SpinBlock* lhsBlock, std::ofstream& ofs, const std::vector<Matrix>& rotateMatrix, const StateInfo *stateinfo ) { // (i,j,k | l ) partition //------------------------- Op_component_base& rhs_array = rhsBlock->get_op_array(rhsType); Op_component_base& lhs_array = lhsBlock->get_op_array(lhsType); assert ( (rhs_array.get_size() == 1) || (lhs_array.get_size() == 1) ); // Initialize filesystem std::ifstream rhsifs; if ( (! dmrginp.do_npdm_in_core()) && rhsBlock->size() > 1 ) rhsifs.open( rhs_array.get_filename().c_str(), std::ios::binary ); // Loop over all rhs operator indices for (int idx = 0; idx < rhs_array.get_size(); ++idx) { std::vector<boost::shared_ptr<SparseMatrix> > rhs_ops; if ( dmrginp.do_npdm_in_core() || rhsBlock->size() <= 1 ) rhs_ops = rhs_array.get_local_element(idx); else rhs_ops = get_ops_from_disk( rhsifs, rhs_array.get_local_element(0).size() ); // Loop over all lhs operator indices for (int iidx = 0; iidx < lhs_array.get_size(); ++iidx) { std::vector<boost::shared_ptr<SparseMatrix> > lhs_ops = lhs_array.get_local_element(iidx); int i = rhs_ops[0]->get_orbs()[0]; int j = rhs_ops[0]->get_orbs()[1]; int k = rhs_ops[0]->get_orbs()[2]; int l = lhs_ops[0]->get_orbs()[0]; // In parallel calculations not all operators are built on each proc if ( ! big.get_op_array(optype).has_local_index(i,j,k,l) ) continue; //pout << "p" << mpigetrank() << "; i,j,k,l = " << i << "," << j << "," << k << "," << l << endl; std::vector<boost::shared_ptr<SparseMatrix> > vec = big.get_op_array(optype).get_element(i,j,k,l); // Loop over rhs spin-op components for (int jdx=0; jdx < rhs_ops.size(); jdx++) { boost::shared_ptr<SparseMatrix>& rhs_op = rhs_ops[jdx]; assert( rhs_op->get_built() ); std::string build_123 = rhs_op->get_build_pattern(); std::vector<SpinQuantum> spin_123 = rhs_op->get_quantum_ladder().at(build_123); // Loop over lhs spin-op components //FIXME for (int jjdx=0; jjdx < lhs_ops.size(); jjdx++) { boost::shared_ptr<SparseMatrix>& lhs_op = lhs_ops[jjdx]; assert( lhs_op->get_built() ); std::string build_4 = lhs_op->get_build_pattern(); std::string build_pattern = "(" + build_123 + build_4 + ")"; // Allocate and build new operator for (int sx=0; sx < vec.size(); sx++) { boost::shared_ptr<SparseMatrix>& op = vec[sx]; // Select relevant spin components std::vector<SpinQuantum> s = { op->get_quantum_ladder().at(build_pattern).at(0), op->get_quantum_ladder().at(build_pattern).at(1) }; // if ( s == spin_123 ) finish_tensor_product( big, rhsBlock, *rhs_op, Transposeview(lhs_op), *op, forwards, build_pattern ); if ( s == spin_123 ) { finish_tensor_product( big, rhsBlock, *rhs_op, *lhs_op, *op, forwards, build_pattern ); // Renormalise operator op->renormalise_transform( rotateMatrix, stateinfo ); } } } } // Store spin-batch on disk if ( ! dmrginp.do_npdm_in_core() ) store_ops_on_disk( ofs, vec ); } } if ( rhsifs.is_open() ) rhsifs.close(); }
void SweepTwopdm::BlockAndDecimate (SweepParams &sweepParams, SpinBlock& system, SpinBlock& newSystem, const bool &useSlater, const bool& dot_with_sys, int state) { //mcheck("at the start of block and decimate"); // figure out if we are going forward or backwards dmrginp.guessgenT -> start(); bool forward = (system.get_sites() [0] == 0); SpinBlock systemDot; SpinBlock envDot; int systemDotStart, systemDotEnd; int systemDotSize = sweepParams.get_sys_add() - 1; if (forward) { systemDotStart = dmrginp.spinAdapted() ? *system.get_sites().rbegin () + 1 : (*system.get_sites().rbegin ())/2 + 1 ; systemDotEnd = systemDotStart + systemDotSize; } else { systemDotStart = dmrginp.spinAdapted() ? system.get_sites()[0] - 1 : (system.get_sites()[0])/2 - 1 ; systemDotEnd = systemDotStart - systemDotSize; } vector<int> spindotsites(2); spindotsites[0] = systemDotStart; spindotsites[1] = systemDotEnd; //if (useSlater) { systemDot = SpinBlock(systemDotStart, systemDotEnd, system.get_integralIndex(), true); //SpinBlock::store(true, systemDot.get_sites(), systemDot); //} //else //SpinBlock::restore(true, spindotsites, systemDot); SpinBlock environment, environmentDot, newEnvironment; int environmentDotStart, environmentDotEnd, environmentStart, environmentEnd; const int nexact = forward ? sweepParams.get_forward_starting_size() : sweepParams.get_backward_starting_size(); system.addAdditionalCompOps(); InitBlocks::InitNewSystemBlock(system, systemDot, newSystem, sweepParams.current_root(), sweepParams.current_root(), sweepParams.get_sys_add(), dmrginp.direct(), system.get_integralIndex(), DISTRIBUTED_STORAGE, true, true); InitBlocks::InitNewEnvironmentBlock(environment, systemDot, newEnvironment, system, systemDot, sweepParams.current_root(), sweepParams.current_root(), sweepParams.get_sys_add(), sweepParams.get_env_add(), forward, dmrginp.direct(), sweepParams.get_onedot(), nexact, useSlater, system.get_integralIndex(), true, true, true); SpinBlock big; newSystem.set_loopblock(true); system.set_loopblock(false); newEnvironment.set_loopblock(false); InitBlocks::InitBigBlock(newSystem, newEnvironment, big); const int nroots = dmrginp.nroots(); std::vector<Wavefunction> solution(1); DiagonalMatrix e; GuessWave::guess_wavefunctions(solution[0], e, big, sweepParams.get_guesstype(), true, state, true, 0.0); #ifndef SERIAL mpi::communicator world; mpi::broadcast(world, solution, 0); #endif std::vector<Matrix> rotateMatrix; DensityMatrix tracedMatrix(newSystem.get_stateInfo()); tracedMatrix.allocate(newSystem.get_stateInfo()); tracedMatrix.makedensitymatrix(solution, big, std::vector<double>(1,1.0), 0.0, 0.0, false); rotateMatrix.clear(); if (!mpigetrank()) double error = makeRotateMatrix(tracedMatrix, rotateMatrix, sweepParams.get_keep_states(), sweepParams.get_keep_qstates()); #ifndef SERIAL mpi::broadcast(world,rotateMatrix,0); #endif #ifdef SERIAL const int numprocs = 1; #endif #ifndef SERIAL const int numprocs = world.size(); #endif if (sweepParams.get_block_iter() == 0) compute_twopdm_initial(solution, system, systemDot, newSystem, newEnvironment, big, numprocs, state); compute_twopdm_sweep(solution, system, systemDot, newSystem, newEnvironment, big, numprocs, state); if (sweepParams.get_block_iter() == sweepParams.get_n_iters() - 1) compute_twopdm_final(solution, system, systemDot, newSystem, newEnvironment, big, numprocs, state); SaveRotationMatrix (newSystem.get_sites(), rotateMatrix, state); //for(int i=0;i<dmrginp.nroots();++i) solution[0].SaveWavefunctionInfo (big.get_stateInfo(), big.get_leftBlock()->get_sites(), state); newSystem.transform_operators(rotateMatrix); }
void SpinAdapted::mps_nevpt::type1::calcHamiltonianAndOverlap(const MPS& statea, double& h, double& o, perturber& pb) { #ifndef SERIAL mpi::communicator world; #endif SpinBlock system, siteblock; bool forward = true, restart=false, warmUp = false; int leftState=0, rightState=0, forward_starting_size=1, backward_starting_size=1, restartSize =0; InitBlocks::InitStartingBlock(system, forward, leftState, rightState, forward_starting_size, backward_starting_size, restartSize, restart, warmUp, 0,statea.getw().get_deltaQuantum(), statea.getw().get_deltaQuantum()); if (dmrginp.outputlevel() > 0) pout << system<<endl; system.transform_operators(const_cast<std::vector<Matrix>&>(statea.getSiteTensors(0)), const_cast<std::vector<Matrix>&>(statea.getSiteTensors(0)), false, false ); int sys_add = true; bool direct = true; for (int i=0; i<mps_nevpt::sweepIters-1; i++) { SpinBlock newSystem; system.addAdditionalCompOps(); InitBlocks::InitNewSystemBlock(system, siteBlocks_noDES[i+1], newSystem, leftState, rightState, sys_add, direct, 0, DISTRIBUTED_STORAGE, false, true,NO_PARTICLE_SPIN_NUMBER_CONSTRAINT,statea.getw().get_deltaQuantum(),statea.getw().get_deltaQuantum()); newSystem.transform_operators(const_cast<std::vector<Matrix>&>(statea.getSiteTensors(i+1)), const_cast<std::vector<Matrix>&>(statea.getSiteTensors(i+1)), false ); system = newSystem; } SpinBlock newSystem, big; system.addAdditionalCompOps(); //system.printOperatorSummary(); //To set implicit_transpose to true. //The last site spinblock should have implicit_transpose true. InitBlocks::InitNewSystemBlock(system, siteBlocks_noDES[mps_nevpt::sweepIters], newSystem, leftState, rightState, sys_add, direct, 0, DISTRIBUTED_STORAGE, false, true,NO_PARTICLE_SPIN_NUMBER_CONSTRAINT,statea.getw().get_deltaQuantum(),statea.getw().get_deltaQuantum()); newSystem.set_loopblock(false); system.set_loopblock(false); newSystem.addAdditionalCompOps(); //siteBlocks_noDES[mps_nevpt::sweepIters+1].set_loopblock(false); InitBlocks::InitBigBlock(newSystem, siteBlocks_noDES[mps_nevpt::sweepIters+1], big,statea.getw().get_deltaQuantum(),statea.getw().get_deltaQuantum()); //FIXME //Assume statea.getw() has only one deltaquantum. //Spin Embeding for zero order wavefunction is needed. Wavefunction temp = statea.getw(); temp.Clear(); big.multiplyH(const_cast<Wavefunction&>(statea.getw()), &temp, 1); if (mpigetrank() == 0) h = DotProduct(statea.getw(), temp); temp.Clear(); big.multiplyOverlap(const_cast<Wavefunction&>(statea.getw()), &temp, 1); if (mpigetrank() == 0) o = DotProduct(statea.getw(), temp); if(dmrginp.spinAdapted()) { double cg= 0.0; //TODO //Assume the zero order wavefunction has a spin zero. //Spin Embeding must be used. SpinQuantum wQ= statea.getw().get_deltaQuantum(0); //cg*= dmrginp.get_ninej()(wQ.get_s().getirrep(), 1, dmrginp.effective_molecule_quantum().get_s().getirrep(), // pb.delta.get_s().getirrep(), pb.delta.get_s().getirrep(), 0, // dmrginp.effective_molecule_quantum().get_s().getirrep(), 0, dmrginp.effective_molecule_quantum().get_s().getirrep()); //cg*= Symmetry::spatial_ninej(wQ.get_symm().getirrep(), -pb.delta.get_symm().getirrep(), dmrginp.effective_molecule_quantum().get_symm().getirrep(), // pb.delta.get_symm().getirrep(), -pb.delta.get_symm().getirrep(), 0, // dmrginp.effective_molecule_quantum().get_symm().getirrep(), 0, dmrginp.effective_molecule_quantum().get_symm().getirrep()); cg += pow(clebsch(wQ.get_s().getirrep(),-1,1,1,0,0),2); cg += pow(clebsch(wQ.get_s().getirrep(),1,1,-1,0,0),2); //cout << "cg coefficient: " <<cg<<endl; h*= cg*cg; o*= cg*cg; } #ifndef SERIAL mpi::broadcast(world, h, 0); mpi::broadcast(world, o, 0); #endif return; }