DOCI-Exact  1.0
doci.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2014 Ward Poelmans
2 
3 This file is part of DOCI-Exact.
4 
5 Doci-Exact is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 Hubbard-GPU is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with DOCI-Exact. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <iostream>
20 #include <sstream>
21 #include <iomanip>
22 #include <chrono>
23 #include <getopt.h>
24 
25 #include "Permutation.h"
26 #include "Molecule.h"
27 #include "DOCIHamtilonian.h"
28 #include "DM2.h"
29 
30 // comment out if you don't need it
31 #include "SymMolecule.h"
32 #include "SimulatedAnnealing.h"
33 #include "Hamiltonian.h"
34 #include "OrbitalTransform.h"
35 #include "UnitaryMatrix.h"
36 #include "LocalMinimizer.h"
37 
50 int main(int argc, char **argv)
51 {
52  using namespace doci;
53  using std::cout;
54  using std::endl;
55 
56  cout.precision(10);
57 
58  std::string integralsfile = "mo-integrals.h5";
59  std::string h5name = "rdm.h5";
60  std::string unitary;
61  bool simanneal = false;
62  bool jacobirots = false;
63  bool random = false;
64 
65  struct option long_options[] =
66  {
67  {"integrals", required_argument, 0, 'i'},
68  {"output", required_argument, 0, 'o'},
69  {"unitary", required_argument, 0, 'u'},
70  {"simulated-annealing", no_argument, 0, 's'},
71  {"jacobi-rotations", no_argument, 0, 'j'},
72  {"random", no_argument, 0, 'r'},
73  {"help", no_argument, 0, 'h'},
74  {0, 0, 0, 0}
75  };
76 
77  int i,j;
78 
79  while( (j = getopt_long (argc, argv, "hi:o:su:jr", long_options, &i)) != -1)
80  switch(j)
81  {
82  case 'h':
83  case '?':
84  cout << "Usage: " << argv[0] << " [OPTIONS]\n"
85  "\n"
86  " -i, --integrals=integrals-file Set the input integrals file\n"
87  " -o, --output=h5-file Set the output filename for the RDM\n"
88  " -s, --simulated-annealing Use stimulated Annealing to find lowest energy\n"
89  " -j, --jacobi-rotations Use Jacobi Rotations to find lowest energy\n"
90  " -u, --unitary Use this unitary to calc energy\n"
91  " -r, --random Use a random unitary as start point\n"
92  " -h, --help Display this help\n"
93  "\n";
94  return 0;
95  break;
96  case 'i':
97  integralsfile = optarg;
98  break;
99  case 'o':
100  h5name = optarg;
101  break;
102  case 's':
103  simanneal = true;
104  break;
105  case 'j':
106  jacobirots = true;
107  break;
108  case 'r':
109  random = true;
110  break;
111  case 'u':
112  unitary = optarg;
113  break;
114  }
115 
116  if(simanneal && jacobirots)
117  {
118  cout << "Cannot do both simulated annealing and jacobi rotations, you have to choose!" << endl;
119 
120  return 2;
121  }
122 
123  // make sure we have a save path, even if it's not specify already
124  // This will not overwrite an already set SAVE_H5_PATH
125  setenv("SAVE_H5_PATH", "./", 0);
126 
127  cout << "Reading: " << integralsfile << endl;
128  Sym_Molecule mol(integralsfile);
129  auto& ham_ints = mol.getHamObject();
130 
131  if(random)
132  {
133  if(!unitary.empty())
134  cout << "Overriding the input unitary " << unitary << " with a random unitary!" << endl;
135 
136  const simanneal::OptIndex opt(ham_ints);
137 
139  X.fill_random();
141  cout << "U=exp(X), X=" << endl;
142  X.print_unitary();
143 
144  simanneal::OrbitalTransform orbtrans(ham_ints);
145  orbtrans.update_unitary(X, false);
146 
147  std::string filename = getenv("SAVE_H5_PATH");
148  filename += "/random-start-unitary.h5";
149 
150  orbtrans.get_unitary().saveU(filename);
151 
152  cout << "Saving random start point to " << filename << endl;
153  unitary = filename;
154  }
155 
156  if(!simanneal && !jacobirots)
157  {
158  if(!unitary.empty())
159  {
160  cout << "Reading unitary " << unitary << endl;
161 
162  simanneal::OrbitalTransform orbtrans(ham_ints);
163 
164  orbtrans.get_unitary().loadU(unitary);
165  orbtrans.fillHamCI(ham_ints);
166  }
167 
168  DOCIHamiltonian ham(mol);
169 
170  auto start = std::chrono::high_resolution_clock::now();
171  ham.Build();
172  auto end = std::chrono::high_resolution_clock::now();
173 
174  cout << "Building took: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() << " s" << endl;
175 
176  start = std::chrono::high_resolution_clock::now();
177  auto eig2 = ham.Diagonalize();
178  end = std::chrono::high_resolution_clock::now();
179 
180  cout << "Diagonalization took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() << " s" << endl;
181 
182  cout << "E = " << eig2.first + mol.get_nucl_rep() << endl;
183 
184  DM2 rdm(mol);
185  auto perm = ham.getPermutation();
186  start = std::chrono::high_resolution_clock::now();
187  rdm.Build(perm, eig2.second);
188  end = std::chrono::high_resolution_clock::now();
189 
190  cout << "Building 2DM took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() << " s" << endl;
191 
192  DM2 rdm_ham(mol);
193 
194  rdm_ham.BuildHamiltonian(mol);
195 
196  cout << "DM2 Energy = " << rdm.Dot(rdm_ham) + mol.get_nucl_rep() << endl;
197  cout << "DM2 Trace = " << rdm.Trace() << endl;
198 
199  std::string h5_name = getenv("SAVE_H5_PATH");
200  h5_name += "/rdm.h5";
201 
202  cout << "Writing 2DM to " << h5_name << endl;
203 
204  rdm.WriteToFile(h5_name);
205 
206  return 0;
207  }
208 
209  if(simanneal)
210  {
211  SimulatedAnnealing opt(mol);
212 
213  if(!unitary.empty())
214  {
215  cout << "Reading unitary " << unitary << endl;
216  opt.getOrbitaltf().get_unitary().loadU(unitary);
217  }
218 
219  opt.Set_start_temp(0.1);
220  opt.Set_delta_temp(0.99);
221  opt.Set_max_angle(1.3);
222  opt.Set_delta_angle(0.999);
223 
224  auto start = std::chrono::high_resolution_clock::now();
225 
226  opt.optimize();
227 
228  auto end = std::chrono::high_resolution_clock::now();
229 
230  cout << "The optimal energy is " << opt.get_energy() << std::endl;
231 
232  cout << "Optimization took: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() << " s" << endl;
233 
234  opt.calc_new_energy();
235 
236  auto &ham = opt.getHam();
237  auto &opt_mol = ham.getMolecule();
238 
239  auto eigs = ham.Diagonalize();
240  cout << "E = " << eigs.first + mol.get_nucl_rep() << endl;
241 
242  DM2 rdm(opt_mol);
243  auto perm = ham.getPermutation();
244  start = std::chrono::high_resolution_clock::now();
245  rdm.Build(perm, eigs.second);
246  end = std::chrono::high_resolution_clock::now();
247 
248  cout << "Building 2DM took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() << " s" << endl;
249 
250  DM2 rdm_ham(opt_mol);
251  rdm_ham.BuildHamiltonian(opt_mol);
252 
253  cout << "DM2 Energy = " << rdm.Dot(rdm_ham) + mol.get_nucl_rep() << endl;
254  cout << "DM2 Trace = " << rdm.Trace() << endl;
255 
256  rdm.WriteToFile(h5name);
257  }
258 
259  if(jacobirots)
260  {
261  LocalMinimizer opt(mol);
262 
263  if(!unitary.empty())
264  {
265  cout << "Reading unitary " << unitary << endl;
266  opt.getOrbitalTf().get_unitary().loadU(unitary);
267  }
268 
269  opt.set_conv_crit(1e-6);
270  opt.Minimize();
271 
272  cout << "The optimal energy is " << opt.get_energy() << std::endl;
273 
274  DM2 rdm_ham(opt.getHam());
275  rdm_ham.BuildHamiltonian(opt.getHam());
276  const DM2 &rdm = opt.get_DM2();
277 
278  cout << "DM2 Energy = " << rdm.Dot(rdm_ham) + mol.get_nucl_rep() << endl;
279  cout << "DM2 Trace = " << rdm.Trace() << endl;
280 
281  std::string h5_name = getenv("SAVE_H5_PATH");
282  h5_name += "/rdm.h5";
283 
284  cout << "Writing 2DM to " << h5_name << endl;
285 
286  rdm.WriteToFile(h5name);
287  }
288 
289 /* PSI_C1_Molecule mol(integralsfile);
290  *
291  * cout << "RHF energy = " << mol.HF_Energy() + mol.get_nucl_rep() << endl;
292  *
293  * DOCIHamiltonian ham(mol);
294  *
295  * auto start = std::chrono::high_resolution_clock::now();
296  * if(getenv("READ_SPARSE_H5_FILE"))
297  * {
298  * std::stringstream h5_name;
299  * h5_name << getenv("READ_SPARSE_H5_FILE");
300  * ham.ReadFromFile(h5_name.str());
301  * }
302  * else
303  * ham.Build();
304  * auto end = std::chrono::high_resolution_clock::now();
305  *
306  * if(getenv("SAVE_SPARSE_H5_FILE"))
307  * {
308  * std::stringstream h5_name;
309  * h5_name << getenv("SAVE_SPARSE_H5_FILE");
310  * ham.SaveToFile(h5_name.str());
311  * }
312  *
313  * cout << "Building took: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() << " s" << endl;
314  *
315  * // auto eig = ham.DiagonalizeFull();
316  * //
317  * // for(unsigned int i=0;i<eig.first.size();i++)
318  * // cout << i << "\t" << eig.first[i] + mol.get_nucl_rep() << endl;
319  *
320  * start = std::chrono::high_resolution_clock::now();
321  * auto eig2 = ham.Diagonalize();
322  * end = std::chrono::high_resolution_clock::now();
323  *
324  * cout << "Diagonalization took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() << " s" << endl;
325  *
326  * cout << "E = " << eig2.first + mol.get_nucl_rep() << endl;
327  *
328  * DM2 rdm(mol);
329  * auto perm = ham.getPermutation();
330  * start = std::chrono::high_resolution_clock::now();
331  * rdm.Build(perm, eig2.second);
332  * end = std::chrono::high_resolution_clock::now();
333  *
334  * cout << "Building 2DM took: " << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() << " s" << endl;
335  *
336  * DM2 rdm_ham(mol);
337  *
338  * rdm_ham.BuildHamiltonian(mol);
339  *
340  * cout << "DM2 Energy = " << rdm.Dot(rdm_ham) + mol.get_nucl_rep() << endl;
341  * cout << "DM2 Trace = " << rdm.Trace() << endl;
342  *
343  * rdm.WriteToFile(h5name);
344  */
345 
346  return 0;
347 }
348 
349 /* vim: set ts=8 sw=4 tw=0 expandtab :*/
simanneal::OrbitalTransform & getOrbitalTf() const
void Minimize(bool dist_choice=false)
double Trace() const
Definition: DM2.cpp:611
void update_unitary(double *step)
std::pair< double, std::vector< double > > Diagonalize() const
doci::DOCIHamiltonian & getHam() const
int main(int argc, char **argv)
Definition: doci.cpp:50
void fillHamCI(CheMPS2::Hamiltonian &HamCI)
void WriteToFile(const std::string) const
Definition: DM2.cpp:213
Definition: DM2.h:24
Molecule const & getMolecule() const
simanneal::OrbitalTransform & getOrbitaltf() const
void set_conv_crit(double)
const doci::DM2 & get_DM2() const
void Build(Permutation &, std::vector< double > &)
Definition: DM2.cpp:373
void BuildHamiltonian(const Molecule &)
Definition: DM2.cpp:537
void saveU(std::string savename) const
Save the unitary to disk.
doci::Sym_Molecule & getHam() const
void loadU(std::string loadname)
Load the unitary from disk.
UnitaryMatrix & get_unitary()
double get_energy() const
double get_nucl_rep() const
Definition: SymMolecule.cpp:48
CheMPS2::Hamiltonian & getHamObject() const
Definition: SymMolecule.cpp:67
double Dot(const DM2 &) const
Definition: DM2.cpp:593
Permutation const & getPermutation() const