12 #include "LocalMinimizer.h"
13 #include "Hamiltonian.h"
32 std::random_device rd;
33 mt = std::mt19937(rd());
36 char *irreps_env = getenv(
"v2DM_DOCI_ALLOWED_IRREPS");
37 if(irreps_env && strlen(irreps_env) > 0)
39 std::string irreps_string = irreps_env;
40 const std::string delim =
",";
44 auto end = irreps_string.find(delim);
49 auto elem = irreps_string.substr(start, end - start);
53 int cur_irrep = std::stoi(elem);
55 if(cur_irrep >= 0 && cur_irrep < syminfo.getNumberOfIrreps())
56 allow_irreps.push_back(cur_irrep);
58 start = end + delim.length();
60 if(end >= std::string::npos)
63 end = irreps_string.find(delim, start);
65 }
catch (std::exception& e) {
66 std::cout <<
"Invalid value in v2DM_DOCI_ALLOWED_IRREPS" << std::endl;
69 std::sort(allow_irreps.begin(), allow_irreps.end());
70 std::cout <<
"Allowed irreps: ";
71 for(
auto &elem: allow_irreps)
72 std::cout << elem <<
" ";
73 std::cout << std::endl;
90 std::random_device rd;
91 mt = std::mt19937(rd());
101 return energy + method->getMolecule().get_nucl_rep();
110 auto start = std::chrono::high_resolution_clock::now();
112 auto end = std::chrono::high_resolution_clock::now();
114 std::cout <<
"Building took: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
116 start = std::chrono::high_resolution_clock::now();
117 auto eig = method->Diagonalize();
119 end = std::chrono::high_resolution_clock::now();
120 std::cout <<
"E = " << eig.first + method->getMolecule().get_nucl_rep() << std::endl;
122 std::cout <<
"Diagonalization took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
124 auto perm = method->getPermutation();
125 start = std::chrono::high_resolution_clock::now();
126 rdm->Build(perm, eig.second);
127 end = std::chrono::high_resolution_clock::now();
129 std::cout <<
"Building 2DM took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
138 auto *mol =
static_cast<Sym_Molecule *
> (&method->getMolecule());
139 assert(mol &&
"Shit, NULL pointer");
141 orbtrans->fillHamCI(mol->getHamObject());
143 auto start = std::chrono::high_resolution_clock::now();
145 auto end = std::chrono::high_resolution_clock::now();
147 std::cout <<
"Building took: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
149 start = std::chrono::high_resolution_clock::now();
150 auto eig = method->Diagonalize();
151 end = std::chrono::high_resolution_clock::now();
152 std::cout <<
"E = " << eig.first + mol->get_nucl_rep() << std::endl;
154 std::cout <<
"Diagonalization took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
156 auto perm = method->getPermutation();
157 start = std::chrono::high_resolution_clock::now();
158 rdm->Build(perm, eig.second);
159 end = std::chrono::high_resolution_clock::now();
161 std::cout <<
"Building 2DM took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
168 auto *mol =
static_cast<Sym_Molecule *
> (&method->getMolecule());
169 assert(mol &&
"Shit, NULL pointer");
173 auto start = std::chrono::high_resolution_clock::now();
175 auto end = std::chrono::high_resolution_clock::now();
177 std::cout <<
"Building took: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
179 start = std::chrono::high_resolution_clock::now();
180 auto eig = method->Diagonalize();
181 end = std::chrono::high_resolution_clock::now();
182 std::cout <<
"E = " << eig.first + mol->get_nucl_rep() << std::endl;
184 std::cout <<
"Diagonalization took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
186 auto perm = method->getPermutation();
187 start = std::chrono::high_resolution_clock::now();
188 rdm->Build(perm, eig.second);
189 end = std::chrono::high_resolution_clock::now();
191 std::cout <<
"Building 2DM took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
198 return orbtrans->get_unitary();
203 auto *mol =
static_cast<Sym_Molecule *
> (&method->getMolecule());
204 assert(mol &&
"Shit, NULL pointer");
216 auto start = std::chrono::high_resolution_clock::now();
218 auto *mol =
static_cast<Sym_Molecule *
> (&method->getMolecule());
219 assert(mol &&
"Shit, NULL pointer");
221 const auto& ham2 = mol->getHamObject();
222 std::function<double(int,int)> getT = [&ham2] (
int a,
int b) ->
double {
return ham2.getTmat(a,b); };
223 std::function<double(int,int,int,int)> getV = [&ham2] (
int a,
int b,
int c,
int d) ->
double {
return ham2.getVmat(a,b,c,d); };
225 std::vector< std::tuple<int,int,double,double> > pos_rotations;
227 pos_rotations.reserve(ham2.getL()*(ham2.getL()-1)/2);
229 for(
int k_in=0;k_in<ham2.getL();k_in++)
230 for(
int l_in=k_in+1;l_in<ham2.getL();l_in++)
231 if(ham2.getOrbitalIrrep(k_in) == ham2.getOrbitalIrrep(l_in))
233 if(!allow_irreps.empty() && std::find(allow_irreps.begin(), allow_irreps.end(), ham2.getOrbitalIrrep(k_in)) == allow_irreps.end() )
236 auto found = rdm->find_min_angle(k_in,l_in,0.3,getT,getV);
240 found = rdm->find_min_angle(k_in,l_in,0.01,getT,getV);
247 if(fabs(found.first)>M_PI/2.0)
250 double new_en = rdm->calc_rotate(k_in,l_in,found.first,getT,getV);
252 assert(found.second &&
"Shit, maximum!");
254 pos_rotations.push_back(std::make_tuple(k_in,l_in,found.first,new_en));
257 auto end = std::chrono::high_resolution_clock::now();
259 std::cout <<
"Orbital scanning took: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
261 assert(pos_rotations.size()>0);
263 return pos_rotations;
277 energy = calc_new_energy();
279 auto start = std::chrono::high_resolution_clock::now();
281 std::pair<int,int> prev_pair(0,0);
285 auto *mol =
static_cast<Sym_Molecule *
> (&method->getMolecule());
286 assert(mol &&
"Shit, NULL pointer");
288 auto& ham2 = mol->getHamObject();
290 while(converged<conv_steps)
292 auto list_rots = scan_orbitals();
294 std::sort(list_rots.begin(), list_rots.end(),
295 [](
const std::tuple<int,int,double,double> & a,
const std::tuple<int,int,double,double> & b) ->
bool
297 return std::get<3>(a) < std::get<3>(b);
300 for(
auto& elem: list_rots)
301 std::cout << std::get<0>(elem) <<
"\t" << std::get<1>(elem) <<
"\t" << std::get<3>(elem)+ham2.getEconst() <<
"\t" << std::get<2>(elem) << std::endl;
304 std::pair<int,int> tmp;
308 idx = choose_orbitalpair(list_rots);
310 tmp = std::make_pair(std::get<0>(list_rots[idx]), std::get<1>(list_rots[idx]));
313 idx = choose_orbitalpair(list_rots);
315 tmp = std::make_pair(std::get<0>(list_rots[idx]), std::get<1>(list_rots[idx]));
321 tmp = std::make_pair(std::get<0>(list_rots[idx]), std::get<1>(list_rots[idx]));
327 const auto& new_rot = list_rots[idx];
328 prev_pair = std::make_pair(std::get<0>(new_rot), std::get<1>(new_rot));
331 std::cout << iters <<
" (" << converged <<
") Chosen: " << idx << std::endl;
333 assert(ham2.getOrbitalIrrep(std::get<0>(new_rot)) == ham2.getOrbitalIrrep(std::get<1>(new_rot)));
335 orbtrans->DoJacobiRotation(ham2, std::get<0>(new_rot), std::get<1>(new_rot), std::get<2>(new_rot));
336 orbtrans->get_unitary().jacobi_rotation(ham2.getOrbitalIrrep(std::get<0>(new_rot)), std::get<0>(new_rot), std::get<1>(new_rot), std::get<2>(new_rot));
338 new_energy = calc_new_energy();
340 std::stringstream h5_name;
344 h5_name << getenv(
"SAVE_H5_PATH") <<
"/unitary-" << iters <<
".h5";
345 orbtrans->get_unitary().saveU(h5_name.str());
351 h5_name << getenv(
"SAVE_H5_PATH") <<
"/ham-" << iters <<
".h5";
352 ham2.save2(h5_name.str());
355 h5_name << getenv(
"SAVE_H5_PATH") <<
"/rdm-" << iters <<
".h5";
356 rdm->WriteToFile(h5_name.str());
359 if(fabs(energy-new_energy)<conv_crit)
362 std::cout << iters <<
" (" << converged <<
")\tRotation between " << std::get<0>(new_rot) <<
" " << std::get<1>(new_rot) <<
" over " << std::get<2>(new_rot) <<
" E_rot = " << std::get<3>(new_rot)+ham2.getEconst() <<
" E = " << new_energy+ham2.getEconst() <<
"\t" << fabs(energy-new_energy) << std::endl;
370 std::cout <<
"Done 1000 steps, quiting..." << std::endl;
375 auto end = std::chrono::high_resolution_clock::now();
377 std::cout <<
"Minimization took: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
379 std::stringstream h5_name;
380 h5_name << getenv(
"SAVE_H5_PATH") <<
"/optimale-uni.h5";
381 get_Optimal_Unitary().saveU(h5_name.str());
407 std::uniform_real_distribution<double> dist(0, 1);
409 const double choice = dist(mt);
413 for(
auto &orb_pair: orbs)
414 norm += (energy - std::get<3>(orb_pair));
417 for(
int i=0;i<orbs.size();i++)
419 cum += (energy - std::get<3>(orbs[i]))/norm;
424 assert(0 &&
"Should never ever be reached!");
simanneal::OrbitalTransform & getOrbitalTf() const
void Minimize(bool dist_choice=false)
simanneal::UnitaryMatrix & get_Optimal_Unitary()
int choose_orbitalpair(std::vector< std::tuple< int, int, double, double >> &)
void set_conv_crit(double)
const doci::DM2 & get_DM2() const
virtual ~LocalMinimizer()
doci::Sym_Molecule & getHam() const
LocalMinimizer(const doci::Sym_Molecule &)
double get_energy() const
int getNGroup() const
Get the group number.
std::vector< std::tuple< int, int, double, double > > scan_orbitals()
CheMPS2::Hamiltonian & getHamObject() const
double get_conv_crit() const