28 #include "Initialize.h" 31 #include "MPIchemps2.h" 32 #include "EdmistonRuedenberg.h" 36 void fetch_ints(
const string rawdata,
int * result,
const int num ){
40 for (
int no = 0; no < num; no++ ){
41 pos2 = rawdata.find(
",", pos );
42 if ( pos2 == string::npos ){ pos2 = rawdata.length(); }
43 result[ no ] = atoi( rawdata.substr( pos, pos2-pos ).c_str() );
49 void fetch_doubles(
const string rawdata,
double * result,
const int num ){
53 for (
int no = 0; no < num; no++ ){
54 pos2 = rawdata.find(
",", pos );
55 if ( pos2 == string::npos ){ pos2 = rawdata.length(); }
56 result[ no ] = atof( rawdata.substr( pos, pos2-pos ).c_str() );
62 bool file_exists(
const string filename,
const string tag ){
64 #ifdef CHEMPS2_MPI_COMPILATION 67 const bool am_i_master =
true;
70 struct stat file_info;
71 const bool on_disk = (( filename.length() > 0 ) && ( stat( filename.c_str(), &file_info ) == 0 ));
72 if (( on_disk ==
false ) && ( am_i_master )){
73 cerr <<
"Unable to retrieve file " << filename <<
"!" << endl;
74 cerr <<
"Invalid option for " << tag <<
"!" << endl;
80 bool find_integer(
int * result,
const string line,
const string tag,
const bool lower_bound,
const int val_lower,
const bool upper_bound,
const int val_upper ){
82 #ifdef CHEMPS2_MPI_COMPILATION 85 const bool am_i_master =
true;
88 if ( line.find( tag ) != string::npos ){
90 const int pos = line.find(
"=" ) + 1;
91 result[ 0 ] = atoi( line.substr( pos, line.length() - pos ).c_str() );
93 const bool lower_ok = (( lower_bound == false ) || ( result[ 0 ] >= val_lower ));
94 const bool upper_ok = (( upper_bound == false ) || ( result[ 0 ] <= val_upper ));
96 if (( lower_ok ==
false ) || ( upper_ok == false )){
99 cerr <<
"Invalid option for " << tag <<
"!" << endl;
109 bool find_double(
double * result,
const string line,
const string tag,
const bool lower_bound,
const double val_lower ){
111 #ifdef CHEMPS2_MPI_COMPILATION 114 const bool am_i_master =
true;
117 if ( line.find( tag ) != string::npos ){
119 const int pos = line.find(
"=" ) + 1;
120 result[ 0 ] = atof( line.substr( pos, line.length() - pos ).c_str() );
122 const bool lower_ok = (( lower_bound == false ) || ( result[ 0 ] >= val_lower ));
124 if ( lower_ok ==
false ){
126 cerr << line << endl;
127 cerr <<
"Invalid option for " << tag <<
"!" << endl;
137 bool find_character(
char * result,
const string line,
const string tag,
char * options,
const int num_options ){
139 #ifdef CHEMPS2_MPI_COMPILATION 142 const bool am_i_master =
true;
145 if ( line.find( tag ) != string::npos ){
147 const int pos = line.find(
"=" ) + 1;
148 string temp = line.substr( pos, line.length() - pos );
149 temp.erase( std::remove( temp.begin(), temp.end(),
' ' ), temp.end() );
150 result[ 0 ] = temp.c_str()[ 0 ];
152 bool encountered =
false;
153 for (
int cnt = 0; cnt < num_options; cnt++ ){
154 if ( options[ cnt ] == result[ 0 ] ){ encountered =
true; }
157 if ( encountered ==
false ){
159 cerr << line << endl;
160 cerr <<
"Invalid option for " << tag <<
"!" << endl;
170 bool find_boolean(
bool * result,
const string line,
const string tag ){
172 #ifdef CHEMPS2_MPI_COMPILATION 175 const bool am_i_master =
true;
178 if ( line.find( tag ) != string::npos ){
180 const int pos = line.find(
"=" ) + 1;
181 const int pos_true = line.substr( pos, line.length() - pos ).find(
"TRUE" );
182 const int pos_false = line.substr( pos, line.length() - pos ).find(
"FALSE" );
183 result[ 0 ] = ( pos_true != string::npos );
185 if (( pos_true == string::npos ) && ( pos_false == string::npos )){
187 cerr << line << endl;
188 cerr <<
"Invalid option for " << tag <<
"!" << endl;
198 int clean_exit(
const int return_code ){
200 #ifdef CHEMPS2_MPI_COMPILATION 201 CheMPS2::MPIchemps2::mpi_finalize();
211 "CheMPS2: a spin-adapted implementation of DMRG for ab initio quantum chemistry\n" 212 "Copyright (C) 2013-2016 Sebastian Wouters\n" 214 "Usage: chemps2 [OPTIONS]\n" 222 " Conventions for the symmetry group and irrep numbers (same as psi4):\n" 224 " | 0 1 2 3 4 5 6 7\n" 225 " ---------|-----------------------------------------\n" 230 " 4 : d2 | A B1 B2 B3\n" 231 " 5 : c2v | A1 A2 B1 B2\n" 232 " 6 : c2h | Ag Bg Au Bu\n" 233 " 7 : d2h | Ag B1g B2g B3g Au B1u B2u B3u\n" 236 " -f, --file=inputfile\n" 237 " Specify the input file.\n" 240 " Print the version of chemps2.\n" 243 " Display this help.\n" 246 " FCIDUMP = /path/to/fcidump\n" 247 " Note that orbital irreps in the FCIDUMP file follow molpro convention!\n" 250 " Set the psi4 symmetry group number [0-7] which corresponds to the FCIDUMP file.\n" 252 " MULTIPLICITY = int\n" 253 " Overwrite the spin multiplicity [2S+1] of the FCIDUMP file.\n" 255 " NELECTRONS = int\n" 256 " Overwrite the number of electrons of the FCIDUMP file.\n" 259 " Overwrite the target wavefunction irrep [0-7] of the FCIDUMP file (psi4 convention).\n" 261 " EXCITATION = int\n" 262 " Set which excitation should be calculated. If zero, the ground state is calculated (default 0).\n" 264 " SWEEP_STATES = int, int, int\n" 265 " Set the number of reduced renormalized basis states for the successive sweep instructions (positive integers).\n" 267 " SWEEP_ENERGY_CONV = flt, flt, flt\n" 268 " Set the energy convergence to stop the successive sweep instructions (positive floats).\n" 270 " SWEEP_MAX_SWEEPS = int, int, int\n" 271 " Set the maximum number of sweeps for the successive sweep instructions (positive integers).\n" 273 " SWEEP_NOISE_PREFAC = flt, flt, flt\n" 274 " Set the noise prefactors for the successive sweep instructions (floats).\n" 276 " SWEEP_DVDSON_RTOL = flt, flt, flt\n" 277 " Set the residual norm tolerance for the Davidson algorithm for the successive sweep instructions (positive floats).\n" 279 " NOCC = int, int, int, int\n" 280 " Set the number of occupied (external core) orbitals per irrep (psi4 irrep ordering).\n" 282 " NACT = int, int, int, int\n" 283 " Set the number of active orbitals per irrep (psi4 irrep ordering).\n" 285 " NVIR = int, int, int, int\n" 286 " Set the number of virtual (secondary) orbitals per irrep (psi4 irrep ordering).\n" 288 " MOLCAS_2RDM = /path/to/2rdm/output\n" 289 " When all orbitals are active orbitals, write out the 2-RDM in HDF5 format when specified (default unspecified).\n" 291 " MOLCAS_3RDM = /path/to/3rdm/output\n" 292 " When all orbitals are active orbitals, write out the 3-RDM in HDF5 format when specified (default unspecified).\n" 294 " MOLCAS_F4RDM = /path/to/f4rdm/output\n" 295 " When all orbitals are active orbitals, write out the 4-RDM contracted with the Fock operator in HDF5 format when specified (default unspecified).\n" 297 " MOLCAS_FOCK = /path/to/fock/input\n" 298 " When all orbitals are active orbitals, read in this file containing the Fock operator (default unspecified).\n" 300 " MOLCAS_REORDER = bool\n" 301 " When all orbitals are active orbitals, switch on orbital reordering based on the Fiedler vector of the exchange matrix (TRUE or FALSE; default FALSE).\n" 303 " SCF_STATE_AVG = bool\n" 304 " Switch on state-averaging (TRUE or FALSE; default FALSE).\n" 306 " SCF_DIIS_THR = flt\n" 307 " Switch on DIIS when the update norm is smaller than the given threshold (default 0.0).\n" 309 " SCF_GRAD_THR = flt\n" 310 " Gradient norm threshold for convergence of the DMRG-SCF orbital rotations (default 1e-6).\n" 312 " SCF_MAX_ITER = int\n" 313 " Specify the maximum number of DMRG-SCF iterations (default 100).\n" 315 " SCF_ACTIVE_SPACE = char\n" 316 " Rotate the active space orbitals: no additional rotations (I), natural orbitals (N), localized and ordered orbitals (L), or ordered orbitals only (F) (default I).\n" 318 " SCF_MOLDEN = /path/to/molden\n" 319 " Rotate the FCIDUMP orbitals to the DMRG-SCF occupied (external core), active, and virtual (secondary) orbitals.\n" 321 " CASPT2_CALC = bool\n" 322 " Switch on the CASPT2 calculation (TRUE or FALSE; default FALSE).\n" 324 " CASPT2_ORBS = char\n" 325 " Perform the DMRG calculation for the 4-RDM in the SCF_ACTIVE_SPACE orbitals (A) or in the pseudocanonical orbitals (P) (default A).\n" 327 " CASPT2_IPEA = flt\n" 328 " Ionization potential - electron affinity shift (default 0.0).\n" 330 " CASPT2_IMAG = flt\n" 331 " Imaginary level shift (default 0.0).\n" 333 " CASPT2_CHECKPT = bool\n" 334 " Create checkpoints to continue the CASPT2 4-RDM calculation over multiple runs (TRUE or FALSE; default FALSE).\n" 336 " CASPT2_CUMUL = bool\n" 337 " Use a cumulant approximation for the CASPT2 4-RDM and overwrite CASPT2_CHECKPT to FALSE (TRUE or FALSE; default FALSE).\n" 339 " PRINT_CORR = bool\n" 340 " Print correlation functions (TRUE or FALSE; default FALSE).\n" 342 " TMP_FOLDER = /path/to/tmp/folder\n" 343 " Overwrite the tmp folder for the renormalized operators. With MPI, separate folders per process can (but do not have to) be used (default /tmp).\n" 347 " $ wget \'https://github.com/SebWouters/CheMPS2/raw/master/tests/matrixelements/N2.CCPVDZ.FCIDUMP\'\n" 348 " $ ls -al N2.CCPVDZ.FCIDUMP\n" 349 " $ wget \'https://github.com/SebWouters/CheMPS2/raw/master/tests/test14.input\'\n" 350 " $ sed -i \"s/path\\/to/tmp/\" test14.input\n" 351 " $ cat test14.input\n" 352 " $ chemps2 --file=test14.input\n" 357 int main(
int argc,
char ** argv ){
359 #ifdef CHEMPS2_MPI_COMPILATION 360 CheMPS2::MPIchemps2::mpi_init();
363 const bool am_i_master =
true;
370 string inputfile =
"";
374 int multiplicity = -1;
379 string sweep_states =
"";
380 string sweep_econv =
"";
381 string sweep_maxit =
"";
382 string sweep_noise =
"";
383 string sweep_rtol =
"";
389 string molcas_2rdm =
"";
390 string molcas_3rdm =
"";
391 string molcas_f4rdm =
"";
392 string molcas_fock =
"";
393 bool molcas_reorder =
false;
395 bool scf_state_avg =
false;
396 double scf_diis_thr = 0.0;
397 double scf_grad_thr = 1e-6;
398 int scf_max_iter = 100;
399 char scf_active_space =
'I';
400 string scf_molden =
"";
402 bool caspt2_calc =
false;
403 char caspt2_orbs =
'A';
404 double caspt2_ipea = 0.0;
405 double caspt2_imag = 0.0;
406 bool caspt2_checkpt =
false;
407 bool caspt2_cumul =
false;
409 bool print_corr =
false;
410 string tmp_folder =
"/tmp";
412 struct option long_options[] =
414 {
"file", required_argument, 0,
'f'},
415 {
"version", no_argument, 0,
'v'},
416 {
"help", no_argument, 0,
'h'},
420 int option_index = 0;
422 while (( c = getopt_long( argc, argv,
"hvf:", long_options, &option_index )) != -1 ){
426 if ( am_i_master ){ print_help(); }
427 return clean_exit( 0 );
430 if ( am_i_master ){ cout <<
"chemps2 version " << CHEMPS2_VERSION << endl; }
431 return clean_exit( 0 );
435 if ( file_exists( inputfile,
"--file" ) ==
false ){
return clean_exit( -1 ); }
440 if ( inputfile.length() == 0 ){
441 if ( am_i_master ){ cerr <<
"The input file should be specified!" << endl; }
442 return clean_exit( -1 );
445 ifstream input( inputfile.c_str() );
447 while ( input.eof() == false ){
449 getline( input, line );
451 if ( line.find(
"FCIDUMP" ) != string::npos ){
452 const int pos = line.find(
"=" ) + 1;
453 fcidump = line.substr( pos, line.length() - pos );
454 fcidump.erase(
remove( fcidump.begin(), fcidump.end(),
' ' ), fcidump.end() );
455 if ( file_exists( fcidump,
"FCIDUMP" ) == false ){
return clean_exit( -1 ); }
458 if ( line.find(
"MOLCAS_2RDM" ) != string::npos ){
459 const int pos = line.find(
"=" ) + 1;
460 molcas_2rdm = line.substr( pos, line.length() - pos );
461 molcas_2rdm.erase(
remove( molcas_2rdm.begin(), molcas_2rdm.end(),
' ' ), molcas_2rdm.end() );
464 if ( line.find(
"MOLCAS_3RDM" ) != string::npos ){
465 const int pos = line.find(
"=" ) + 1;
466 molcas_3rdm = line.substr( pos, line.length() - pos );
467 molcas_3rdm.erase(
remove( molcas_3rdm.begin(), molcas_3rdm.end(),
' ' ), molcas_3rdm.end() );
470 if ( line.find(
"MOLCAS_F4RDM" ) != string::npos ){
471 const int pos = line.find(
"=" ) + 1;
472 molcas_f4rdm = line.substr( pos, line.length() - pos );
473 molcas_f4rdm.erase(
remove( molcas_f4rdm.begin(), molcas_f4rdm.end(),
' ' ), molcas_f4rdm.end() );
476 if ( line.find(
"MOLCAS_FOCK" ) != string::npos ){
477 const int pos = line.find(
"=" ) + 1;
478 molcas_fock = line.substr( pos, line.length() - pos );
479 molcas_fock.erase(
remove( molcas_fock.begin(), molcas_fock.end(),
' ' ), molcas_fock.end() );
480 if ( file_exists( molcas_fock,
"MOLCAS_FOCK" ) == false ){
return clean_exit( -1 ); }
483 if ( line.find(
"SCF_MOLDEN" ) != string::npos ){
484 const int pos = line.find(
"=" ) + 1;
485 scf_molden = line.substr( pos, line.length() - pos );
486 scf_molden.erase(
remove( scf_molden.begin(), scf_molden.end(),
' ' ), scf_molden.end() );
487 if ( file_exists( scf_molden,
"SCF_MOLDEN" ) == false ){
return clean_exit( -1 ); }
490 if ( line.find(
"TMP_FOLDER" ) != string::npos ){
491 const int pos = line.find(
"=" ) + 1;
492 tmp_folder = line.substr( pos, line.length() - pos );
493 tmp_folder.erase(
remove( tmp_folder.begin(), tmp_folder.end(),
' ' ), tmp_folder.end() );
494 if ( file_exists( tmp_folder,
"TMP_FOLDER" ) == false ){
return clean_exit( -1 ); }
497 if ( find_integer( &group, line,
"GROUP",
true, 0,
true, 7 ) ==
false ){
return clean_exit( -1 ); }
498 if ( find_integer( &multiplicity, line,
"MULTIPLICITY",
true, 1,
false, -1 ) ==
false ){
return clean_exit( -1 ); }
499 if ( find_integer( &nelectrons, line,
"NELECTRONS",
true, 2,
false, -1 ) ==
false ){
return clean_exit( -1 ); }
500 if ( find_integer( &irrep, line,
"IRREP",
true, 0,
true, 7 ) ==
false ){
return clean_exit( -1 ); }
501 if ( find_integer( &excitation, line,
"EXCITATION",
true, 0,
false, -1 ) ==
false ){
return clean_exit( -1 ); }
502 if ( find_integer( &scf_max_iter, line,
"SCF_MAX_ITER",
true, 1,
false, -1 ) ==
false ){
return clean_exit( -1 ); }
504 if ( find_double( &scf_diis_thr, line,
"SCF_DIIS_THR",
true, 0.0 ) ==
false ){
return clean_exit( -1 ); }
505 if ( find_double( &scf_grad_thr, line,
"SCF_GRAD_THR",
true, 0.0 ) ==
false ){
return clean_exit( -1 ); }
506 if ( find_double( &caspt2_ipea, line,
"CASPT2_IPEA",
true, 0.0 ) ==
false ){
return clean_exit( -1 ); }
507 if ( find_double( &caspt2_imag, line,
"CASPT2_IMAG",
true, 0.0 ) ==
false ){
return clean_exit( -1 ); }
509 char options1[] = {
'I',
'N',
'L',
'F' };
510 char options2[] = {
'A',
'P' };
511 if ( find_character( &scf_active_space, line,
"SCF_ACTIVE_SPACE", options1, 4 ) ==
false ){
return clean_exit( -1 ); }
512 if ( find_character( &caspt2_orbs, line,
"CASPT2_ORBS", options2, 2 ) ==
false ){
return clean_exit( -1 ); }
514 if ( find_boolean( &molcas_reorder, line,
"MOLCAS_REORDER" ) ==
false ){
return clean_exit( -1 ); }
515 if ( find_boolean( &scf_state_avg, line,
"SCF_STATE_AVG" ) ==
false ){
return clean_exit( -1 ); }
516 if ( find_boolean( &caspt2_calc, line,
"CASPT2_CALC" ) ==
false ){
return clean_exit( -1 ); }
517 if ( find_boolean( &caspt2_checkpt, line,
"CASPT2_CHECKPT" ) ==
false ){
return clean_exit( -1 ); }
518 if ( find_boolean( &caspt2_cumul, line,
"CASPT2_CUMUL" ) ==
false ){
return clean_exit( -1 ); }
519 if ( find_boolean( &print_corr, line,
"PRINT_CORR" ) ==
false ){
return clean_exit( -1 ); }
521 if ( line.find(
"SWEEP_STATES" ) != string::npos ){
522 const int pos = line.find(
"=" ) + 1;
523 sweep_states = line.substr( pos, line.length() - pos );
526 if ( line.find(
"SWEEP_ENERGY_CONV" ) != string::npos ){
527 const int pos = line.find(
"=" ) + 1;
528 sweep_econv = line.substr( pos, line.length() - pos );
531 if ( line.find(
"SWEEP_MAX_SWEEPS" ) != string::npos ){
532 const int pos = line.find(
"=" ) + 1;
533 sweep_maxit = line.substr( pos, line.length() - pos );
536 if ( line.find(
"SWEEP_NOISE_PREFAC" ) != string::npos ){
537 const int pos = line.find(
"=" ) + 1;
538 sweep_noise = line.substr( pos, line.length() - pos );
541 if ( line.find(
"SWEEP_DVDSON_RTOL" ) != string::npos ){
542 const int pos = line.find(
"=" ) + 1;
543 sweep_rtol = line.substr( pos, line.length() - pos );
546 if ( line.find(
"NOCC" ) != string::npos ){
547 const int pos = line.find(
"=" ) + 1;
548 nocc = line.substr( pos, line.length() - pos );
551 if ( line.find(
"NACT" ) != string::npos ){
552 const int pos = line.find(
"=" ) + 1;
553 nact = line.substr( pos, line.length() - pos );
556 if ( line.find(
"NVIR" ) != string::npos ){
557 const int pos = line.find(
"=" ) + 1;
558 nvir = line.substr( pos, line.length() - pos );
569 if ( am_i_master ){ cerr <<
"GROUP is a mandatory option!" << endl; }
570 return clean_exit( -1 );
573 const int num_irreps = Symmhelper.getNumberOfIrreps();
575 int fcidump_norb = -1;
576 int fcidump_nelec = -1;
577 int fcidump_two_s = -1;
578 int fcidump_irrep = -1;
580 ifstream thefcidump( fcidump.c_str() );
583 getline( thefcidump, line );
584 pos = line.find(
"FCI" );
585 if ( pos == string::npos ){
586 if ( am_i_master ){ cerr <<
"The file " << fcidump <<
" is not a fcidump file!" << endl; }
587 return clean_exit( -1 );
589 pos = line.find(
"NORB" ); pos = line.find(
"=", pos ); pos2 = line.find(
",", pos );
590 fcidump_norb = atoi( line.substr( pos+1, pos2-pos-1 ).c_str() );
591 pos = line.find(
"NELEC" ); pos = line.find(
"=", pos ); pos2 = line.find(
",", pos );
592 fcidump_nelec = atoi( line.substr( pos+1, pos2-pos-1 ).c_str() );
593 pos = line.find(
"MS2" ); pos = line.find(
"=", pos ); pos2 = line.find(
",", pos );
594 fcidump_two_s = atoi( line.substr( pos+1, pos2-pos-1 ).c_str() );
595 do { getline( thefcidump, line ); }
while ( line.find(
"ISYM" ) == string::npos );
596 pos = line.find(
"ISYM" ); pos = line.find(
"=", pos ); pos2 = line.find(
",", pos );
597 const int molpro_wfn_irrep = atoi( line.substr( pos+1, pos2-pos-1 ).c_str() );
600 int * psi2molpro =
new int[ num_irreps ];
601 Symmhelper.symm_psi2molpro( psi2molpro );
602 for (
int cnt = 0; cnt < num_irreps; cnt++ ){
603 if ( molpro_wfn_irrep == psi2molpro[ cnt ] ){ fcidump_irrep = cnt; }
605 if ( fcidump_irrep == -1 ){
606 if ( am_i_master ){ cerr <<
"Could not find the molpro wavefunction symmetry (ISYM) in the fcidump file!" << endl; }
607 return clean_exit( -1 );
609 delete [] psi2molpro;
611 if ( multiplicity == -1 ){ multiplicity = fcidump_two_s + 1; }
612 if ( nelectrons == -1 ){ nelectrons = fcidump_nelec; }
613 if ( irrep == -1 ){ irrep = fcidump_irrep; }
619 if (( sweep_states.length() == 0 ) || ( sweep_econv.length() == 0 ) || ( sweep_maxit.length() == 0 ) || ( sweep_noise.length() == 0 ) || ( sweep_rtol.length() == 0 )){
620 if ( am_i_master ){ cerr <<
"SWEEP_* are mandatory options!" << endl; }
621 return clean_exit( -1 );
623 const int ni_d = count( sweep_states.begin(), sweep_states.end(),
',' ) + 1;
624 const int ni_econv = count( sweep_econv.begin(), sweep_econv.end(),
',' ) + 1;
625 const int ni_maxit = count( sweep_maxit.begin(), sweep_maxit.end(),
',' ) + 1;
626 const int ni_noise = count( sweep_noise.begin(), sweep_noise.end(),
',' ) + 1;
627 const int ni_rtol = count( sweep_rtol.begin(), sweep_rtol.end(),
',' ) + 1;
628 const bool num_eq = (( ni_d == ni_econv ) && ( ni_d == ni_maxit ) && ( ni_d == ni_noise ) && ( ni_d == ni_rtol ));
630 if ( num_eq ==
false ){
631 if ( am_i_master ){ cerr <<
"The number of instructions in SWEEP_* should be equal!" << endl; }
632 return clean_exit( -1 );
635 int * value_states =
new int [ ni_d ]; fetch_ints( sweep_states, value_states, ni_d );
636 double * value_econv =
new double[ ni_d ]; fetch_doubles( sweep_econv, value_econv, ni_d );
637 int * value_maxit =
new int [ ni_d ]; fetch_ints( sweep_maxit, value_maxit, ni_d );
638 double * value_noise =
new double[ ni_d ]; fetch_doubles( sweep_noise, value_noise, ni_d );
639 double * value_rtol =
new double[ ni_d ]; fetch_doubles( sweep_rtol, value_rtol, ni_d );
645 if (( nocc.length() == 0 ) || ( nact.length() == 0 ) || ( nvir.length() == 0 )){
646 if ( am_i_master ){ cerr <<
"NOCC, NACT, and NVIR are mandatory options!" << endl; }
647 return clean_exit( -1 );
650 const int ni_occ = count( nocc.begin(), nocc.end(),
',' ) + 1;
651 const int ni_act = count( nact.begin(), nact.end(),
',' ) + 1;
652 const int ni_vir = count( nvir.begin(), nvir.end(),
',' ) + 1;
653 const bool cas_ok = (( ni_occ == ni_act ) && ( ni_occ == ni_vir ) && ( ni_occ == num_irreps ));
655 if ( cas_ok ==
false ){
656 if ( am_i_master ){ cerr <<
"There should be " << num_irreps <<
" numbers in NOCC, NACT, and NVIR!" << endl; }
657 return clean_exit( -1 );
660 int * nocc_parsed =
new int[ ni_occ ]; fetch_ints( nocc, nocc_parsed, ni_occ );
661 int * nact_parsed =
new int[ ni_act ]; fetch_ints( nact, nact_parsed, ni_act );
662 int * nvir_parsed =
new int[ ni_vir ]; fetch_ints( nvir, nvir_parsed, ni_vir );
668 bool full_active_space_calculation =
true;
669 for (
int cnt = 0; cnt < num_irreps; cnt++ ){
670 if ( nocc_parsed[ cnt ] != 0 ){ full_active_space_calculation =
false; }
671 if ( nvir_parsed[ cnt ] != 0 ){ full_active_space_calculation =
false; }
674 if ( ( molcas_2rdm.length() != 0 ) || ( molcas_3rdm.length() != 0 ) || ( molcas_f4rdm.length() != 0 ) || ( molcas_fock.length() != 0 ) ){
675 if ( full_active_space_calculation ==
false ){
676 if ( am_i_master ){ cerr <<
"The options MOLCAS_* can only be specified for full active space calculations (when NOCC = NVIR = 0)!" << endl; }
677 return clean_exit( -1 );
681 if ( ( molcas_f4rdm.length() != 0 ) && ( molcas_fock.length() == 0 ) ){
682 if ( am_i_master ){ cerr <<
"When MOLCAS_F4RDM should be written, MOLCAS_FOCK should be specified as well!" << endl; }
683 return clean_exit( -1 );
691 cout <<
"\nRunning chemps2 version " << CHEMPS2_VERSION <<
" with the following options:\n" << endl;
692 cout <<
" FCIDUMP = " << fcidump << endl;
693 cout <<
" GROUP = " << Symmhelper.getGroupName() << endl;
694 cout <<
" MULTIPLICITY = " << multiplicity << endl;
695 cout <<
" NELECTRONS = " << nelectrons << endl;
696 cout <<
" IRREP = " << Symmhelper.getIrrepName( irrep ) << endl;
697 cout <<
" EXCITATION = " << excitation << endl;
698 cout <<
" SWEEP_STATES = [ " << value_states[ 0 ];
for (
int cnt = 1; cnt < ni_d; cnt++ ){ cout <<
" ; " << value_states[ cnt ]; } cout <<
" ]" << endl;
699 cout <<
" SWEEP_ENERGY_CONV = [ " << value_econv [ 0 ];
for (
int cnt = 1; cnt < ni_d; cnt++ ){ cout <<
" ; " << value_econv [ cnt ]; } cout <<
" ]" << endl;
700 cout <<
" SWEEP_MAX_SWEEPS = [ " << value_maxit [ 0 ];
for (
int cnt = 1; cnt < ni_d; cnt++ ){ cout <<
" ; " << value_maxit [ cnt ]; } cout <<
" ]" << endl;
701 cout <<
" SWEEP_NOISE_PREFAC = [ " << value_noise [ 0 ];
for (
int cnt = 1; cnt < ni_d; cnt++ ){ cout <<
" ; " << value_noise [ cnt ]; } cout <<
" ]" << endl;
702 cout <<
" SWEEP_DVDSON_RTOL = [ " << value_rtol [ 0 ];
for (
int cnt = 1; cnt < ni_d; cnt++ ){ cout <<
" ; " << value_rtol [ cnt ]; } cout <<
" ]" << endl;
703 cout <<
" NOCC = [ " << nocc_parsed[ 0 ];
for (
int cnt = 1; cnt < num_irreps; cnt++ ){ cout <<
" ; " << nocc_parsed[ cnt ]; } cout <<
" ]" << endl;
704 cout <<
" NACT = [ " << nact_parsed[ 0 ];
for (
int cnt = 1; cnt < num_irreps; cnt++ ){ cout <<
" ; " << nact_parsed[ cnt ]; } cout <<
" ]" << endl;
705 cout <<
" NVIR = [ " << nvir_parsed[ 0 ];
for (
int cnt = 1; cnt < num_irreps; cnt++ ){ cout <<
" ; " << nvir_parsed[ cnt ]; } cout <<
" ]" << endl;
706 if ( full_active_space_calculation ){
707 cout <<
" MOLCAS_2RDM = " << molcas_2rdm << endl;
708 cout <<
" MOLCAS_3RDM = " << molcas_3rdm << endl;
709 cout <<
" MOLCAS_F4RDM = " << molcas_f4rdm << endl;
710 cout <<
" MOLCAS_FOCK = " << molcas_fock << endl;
711 cout <<
" MOLCAS_REORDER = " << (( molcas_reorder ) ?
"TRUE" :
"FALSE" ) << endl;
713 cout <<
" SCF_STATE_AVG = " << (( scf_state_avg ) ?
"TRUE" :
"FALSE" ) << endl;
714 cout <<
" SCF_DIIS_THR = " << scf_diis_thr << endl;
715 cout <<
" SCF_GRAD_THR = " << scf_grad_thr << endl;
716 cout <<
" SCF_MAX_ITER = " << scf_max_iter << endl;
717 cout <<
" SCF_ACTIVE_SPACE = " << (( scf_active_space ==
'I' ) ?
"I : no additional rotations" :
718 (( scf_active_space ==
'N' ) ?
"N : natural orbitals" :
719 (( scf_active_space ==
'L' ) ?
"L : localized and ordered orbitals" :
"F : ordered orbitals only" ))) << endl;
720 cout <<
" SCF_MOLDEN = " << scf_molden << endl;
721 cout <<
" CASPT2_CALC = " << (( caspt2_calc ) ?
"TRUE" :
"FALSE" ) << endl;
722 cout <<
" CASPT2_ORBS = " << (( caspt2_orbs ==
'A' ) ?
"A : as specified in SCF_ACTIVE_SPACE" :
"P : pseudocanonical orbitals" ) << endl;
723 cout <<
" CASPT2_IPEA = " << caspt2_ipea << endl;
724 cout <<
" CASPT2_IMAG = " << caspt2_imag << endl;
725 cout <<
" CASPT2_CHECKPT = " << (( caspt2_checkpt ) ?
"TRUE" :
"FALSE" ) << endl;
726 cout <<
" CASPT2_CUMUL = " << (( caspt2_cumul ) ?
"TRUE" :
"FALSE" ) << endl;
728 cout <<
" PRINT_CORR = " << (( print_corr ) ?
"TRUE" :
"FALSE" ) << endl;
729 cout <<
" TMP_FOLDER = " << tmp_folder << endl;
740 for (
int count = 0; count < ni_d; count++ ){
742 value_econv [ count ],
743 value_maxit [ count ],
744 value_noise [ count ],
745 value_rtol [ count ] );
747 delete [] value_states;
748 delete [] value_econv;
749 delete [] value_maxit;
750 delete [] value_noise;
751 delete [] value_rtol;
753 if ( full_active_space_calculation ){
758 if (( group == 7 ) && ( molcas_reorder ==
false )){ prob->
SetupReorderD2h(); }
759 if ( molcas_reorder ){
760 int * dmrg2ham =
new int[ ham->
getL() ];
766 #ifdef CHEMPS2_MPI_COMPILATION 767 CheMPS2::MPIchemps2::broadcast_array_int( dmrg2ham, ham->
getL(), MPI_CHEMPS2_MASTER );
777 for (
int state = 0; state < ( excitation + 1 ); state++ ){
778 if ( state > 0 ){ dmrgsolver->
newExcitation( fabs( DMRG_ENERGY ) ); }
779 DMRG_ENERGY = dmrgsolver->
Solve();
780 if (( state == 0 ) && ( excitation > 0 )){ dmrgsolver->
activateExcitations( excitation ); }
784 const bool calc_3rdm = (( molcas_3rdm.length() != 0 ) || ( molcas_f4rdm.length() != 0 ));
785 const bool calc_2rdm = (( print_corr == true ) || ( molcas_2rdm.length() != 0 ));
786 if (( calc_2rdm ) || ( calc_3rdm )){
788 if ( molcas_2rdm.length() != 0 ){ dmrgsolver->
get2DM()->
save_HAM( molcas_2rdm ); }
789 if ( molcas_3rdm.length() != 0 ){ dmrgsolver->
get3DM()->
save_HAM( molcas_3rdm ); }
790 if ( molcas_f4rdm.length() != 0 ){
791 const int LAS = ham->
getL();
792 const int LAS_pow6 = LAS * LAS * LAS * LAS * LAS * LAS;
793 double * fockmx =
new double[ LAS * LAS ];
794 double * work =
new double[ LAS_pow6 ];
795 double * result =
new double[ LAS_pow6 ];
796 for (
int cnt = 0; cnt < LAS_pow6; cnt++ ){ result[ cnt ] = 0.0; }
797 ham->
readfock( molcas_fock, fockmx,
true );
815 CheMPS2::CASSCF koekoek( ham, NULL, NULL, nocc_parsed, nact_parsed, nvir_parsed, tmp_folder );
817 const int root_num = excitation + 1;
833 const double E_CASSCF = koekoek.solve( nelectrons, multiplicity - 1, irrep, opt_scheme, root_num, scf_options );
834 double E_CASPT2 = 0.0;
836 E_CASPT2 = koekoek.caspt2( nelectrons, multiplicity - 1, irrep, opt_scheme, root_num, scf_options, caspt2_ipea, caspt2_imag, ( caspt2_orbs ==
'P' ), caspt2_checkpt, caspt2_cumul );
838 cout <<
"E_CASSCF + E_CASPT2 = E_0 + E_1 + E_2 = " << E_CASSCF + E_CASPT2 << endl;
842 if ( ( am_i_master ) && ( scf_molden.length() > 0 ) ){
843 int * norb_ham =
new int[ Symmhelper.getNumberOfIrreps() ];
844 for (
int irrep = 0; irrep < Symmhelper.getNumberOfIrreps(); irrep++ ){ norb_ham[ irrep ] = 0; }
845 for (
int orb = 0; orb < ham->
getL(); orb++ ){ norb_ham[ ham->
getOrbitalIrrep( orb ) ] += 1; }
849 molden_rotator->
print( scf_molden, scf_molden +
".rotated" );
851 delete molden_rotator;
860 delete [] nocc_parsed;
861 delete [] nact_parsed;
862 delete [] nvir_parsed;
866 return clean_exit( 0 );
void setDumpCorrelations(const bool DumpCorrelations_in)
Set whether the correlations and two-orbital mutual information should be printed.
void print(const string original, const string output)
Multiply and print the new molden file.
void setDoDIIS(const bool DoDIIS_in)
Set whether DIIS should be performed.
void setStartLocRandom(const bool StartLocRandom_in)
Set whether the localization procedure should start from a random unitary.
void readfock(const string fockfile, double *fockmx, const bool printinfo) const
Read in a FOCK file.
void read_molden(const string filename)
Read a molden file.
void setGradientThreshold(const double GradientThreshold_in)
Set the threshold for DMRGSCF convergence.
void save_HAM(const string filename) const
Save the 3-RDM to disk in Hamiltonian indices.
void set_instruction(const int instruction, const int D, const double energy_conv, const int max_sweeps, const double noise_prefactor, const double davidson_rtol)
Set an instruction.
void deleteStoredMPS()
Call "rm " + CheMPS2::DMRG_MPS_storage_prefix + "*.h5".
void read_unitary(const string filename)
Read a unitary matrix.
void Print(const int precision=6, const int columnsPerLine=8) const
Print the correlation functions and two-orbital mutual information.
int getOrbitalIrrep(const int nOrb) const
Get an orbital irrep number.
static int mpi_rank()
Get the rank of this MPI process.
double getVmat(const int index1, const int index2, const int index3, const int index4) const
Get a Vmat element.
Correlations * getCorrelations()
Get the pointer to the Correlations.
static void save_HAM_generic(const string filename, const int LAS, const string tag, double *array)
Generic save routine for objects of size LAS**6.
TwoDM * get2DM()
Get the pointer to the 2-RDM.
void setWhichActiveSpace(const int WhichActiveSpace_in)
Set which active space should be considered in the DMRG routine.
void setup_reorder_custom(int *dmrg2ham)
Reorder the orbitals to a custom ordering. Previous reorderings are cleared.
void FiedlerGlobal(int *dmrg2ham) const
Permute the orbitals so that the bandwidth of the exchange matrix is (approximately) minimized...
string getDIISStorageName() const
Get the DIIS checkpoint filename.
void newExcitation(const double EshiftIn)
Push back current calculation and set everything up to calculate a (new) excitation.
static void fock_dot_4rdm(double *fockmx, CheMPS2::DMRG *dmrgsolver, CheMPS2::Hamiltonian *ham, int next_orb1, int next_orb2, double *work, double *result, const bool CHECKPOINT, const bool PSEUDOCANONICAL)
Build the contraction of the fock matrix with the 4-RDM.
void setStoreDIIS(const bool StoreDIIS_in)
Set whether the DIIS checkpoint should be stored to disk.
void setMaxIterations(const int MaxIterations_in)
Set the maximum number of DMRGSCF iterations.
bool getStoreDIIS() const
Get whether the DIIS checkpoint should be stored to disk.
void SetupReorderD2h()
Reorder the orbitals, so that they form irrep blocks, with order of irreps Ag B1u B3u B2g B2u B3g B1g...
void activateExcitations(const int maxExcIn)
Activate the necessary storage and machinery to handle excitations.
static void Init()
Initialize the random number generator and the cout.precision.
ThreeDM * get3DM()
Get the pointer to the 3-RDM.
void calc_rdms_and_correlations(const bool do_3rdm, const bool disk_3rdm=false)
Calculate the reduced density matrices and correlations. Afterwards the MPS is again in LLLLLLLC gaug...
void setStoreUnitary(const bool StoreUnitary_in)
Set whether the Orbital Rotation checkpoint should be stored to disk.
void save_HAM(const string filename) const
Save the 2-RDM-A to disk in Hamiltonian indices.
void deleteStoredOperators()
Call "rm " + tempfolder + "/" + CheMPS2::DMRG_OPERATOR_storage_prefix + string(thePID) + "*...
int getL() const
Get the number of orbitals.
void setDIISGradientBranch(const double DIISGradientBranch_in)
Set the threshold for when DIIS should start.
string getUnitaryStorageName() const
Get the Orbital Rotation checkpoint filename.
void setStateAveraging(const bool StateAveraging_in)
Set whether state-averaging or state-specific DMRGSCF should be performed.