CheMPS2
Molden.cpp
1 /*
2  CheMPS2: a spin-adapted implementation of DMRG for ab initio quantum chemistry
3  Copyright (C) 2013-2016 Sebastian Wouters
4 
5  This program 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 2 of the License, or
8  (at your option) any later version.
9 
10  This program 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 along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <stdlib.h>
21 #include <iostream>
22 #include <fstream>
23 #include <math.h>
24 #include <assert.h>
25 
26 #include "Molden.h"
27 #include "Lapack.h"
28 #include "DMRGSCFmatrix.h"
29 
30 using std::ifstream;
31 using std::ofstream;
32 
33 CheMPS2::Molden::Molden( const int L, const int group, int * irrep_sizes ){
34 
35  this->L = L;
36  SymmInfo.setGroup( group );
37  this->num_irreps = SymmInfo.getNumberOfIrreps();
38 
39  Isizes = new int[ num_irreps ];
40  molden = new double*[ num_irreps ];
41  unitary = new double*[ num_irreps ];
42  product = new double*[ num_irreps ];
43 
44  for ( int irrep = 0; irrep < num_irreps; irrep++ ){
45  Isizes [ irrep ] = irrep_sizes[ irrep ];
46  molden [ irrep ] = new double[ Isizes[ irrep ] * L ];
47  unitary[ irrep ] = new double[ Isizes[ irrep ] * Isizes[ irrep ] ];
48  product[ irrep ] = new double[ Isizes[ irrep ] * L ];
49  }
50 
51 }
52 
54 
55  for ( int irrep = 0; irrep < num_irreps; irrep++ ){
56  delete [] molden[ irrep ];
57  delete [] unitary[ irrep ];
58  delete [] product[ irrep ];
59  }
60 
61  delete [] molden;
62  delete [] unitary;
63  delete [] product;
64  delete [] Isizes;
65 
66 }
67 
68 void CheMPS2::Molden::read_molden( const string filename ){
69 
70  int * Icounter = new int[ num_irreps ];
71  for ( int irrep = 0; irrep < num_irreps; irrep++ ){ Icounter[ irrep ] = 0; }
72 
73  int * psi2molpro = new int[ num_irreps ];
74  CheMPS2::Irreps::symm_psi2molpro( psi2molpro, SymmInfo.getGroupName() );
75 
76  string line, part;
77 
78  std::ifstream inputfile( filename.c_str() );
79 
80  bool stop = false;
81  string start = "[MO]";
82  do {
83  getline( inputfile, line );
84  const int pos = line.find( start );
85  if ( pos != string::npos ){ stop = true; }
86  } while ( stop == false );
87 
88  int total_num_orbs = 0;
89  for ( int irrep = 0; irrep < num_irreps; irrep++ ){ total_num_orbs += Isizes[ irrep ]; }
90 
91  for ( int orbs = 0; orbs < total_num_orbs; orbs++ ){ // Only read in the alpha orbitals
92 
93  // Read in the Symm
94  getline( inputfile, line );
95  const int pos_equal = line.find( '=' );
96  const int pos_dot = line.find( '.', pos_equal + 1 );
97  int psi4_irrep = -1;
98  if ( pos_dot != string::npos ){ // Molpro
99  part = line.substr( pos_dot + 1, line.size() - 1 - pos_dot );
100  const int molpro_irrep = atoi( part.c_str() );
101  for ( int irrep = 0; irrep < num_irreps; irrep++ ){
102  if ( psi2molpro[ irrep ] == molpro_irrep ){ psi4_irrep = irrep; }
103  }
104  //std::cout << "MO " << orbs + 1 << " has molpro_irrep " << molpro_irrep << " and psi4_irrep " << SymmInfo.getIrrepName( psi4_irrep ) << "." << std::endl;
105  } else { // Psi4
106  part = line.substr( pos_equal + 1, line.size() - 1 - pos_equal );
107  for ( int irrep = 0; irrep < num_irreps; irrep++ ){
108  if ( part.find( SymmInfo.getIrrepName( irrep ) ) != string::npos ){ psi4_irrep = irrep; }
109  }
110  if ( SymmInfo.getGroupNumber() == 3 ){ // Cs
111  if ( part.find( "A'" ) != string::npos ){ psi4_irrep = 0; }
112  if ( part.find( "A\"" ) != string::npos ){ psi4_irrep = 1; }
113  }
114  //std::cout << "MO " << orbs + 1 << " has psi4_irrep " << SymmInfo.getIrrepName( psi4_irrep ) << "." << std::endl;
115  }
116  assert( psi4_irrep != -1 );
117 
118  // Read in the Ene, Spin, Occup lines
119  for ( int cnt = 0; cnt < 3; cnt++ ){ getline( inputfile, line ); }
120 
121  for ( int cnt = 0; cnt < L; cnt++ ){
122  getline( inputfile, line );
123  const int pos_number = line.find_first_not_of( ' ' ); // Start of the primitive counter number
124  const int pos_gap = line.find( ' ', pos_number ); // Gap between the primitive number and the actual coefficient
125  part = line.substr( pos_gap + 1, line.size() - 1 - pos_gap );
126  const double value = atof( part.c_str() );
127  molden[ psi4_irrep ][ cnt + L * Icounter[ psi4_irrep ] ] = value;
128  //std::cout << cnt+1 << " " << value << std::endl;
129  }
130 
131  Icounter[ psi4_irrep ] += 1;
132 
133  }
134 
135  for ( int irrep = 0; irrep < num_irreps; irrep++ ){
136  assert( Icounter[ irrep ] == Isizes[ irrep ] );
137  }
138 
139  delete [] Icounter;
140  delete [] psi2molpro;
141 
142  inputfile.close();
143 
144 }
145 
146 void CheMPS2::Molden::read_unitary( const string filename ){
147 
148  CheMPS2::DMRGSCFmatrix::read( filename, num_irreps, unitary );
149 
150 }
151 
152 void CheMPS2::Molden::print( const string original, const string output ){
153 
154  char trans = 'T';
155  char notrans = 'N';
156  double one = 1.0;
157  double set = 0.0;
158  for ( int irrep = 0; irrep < num_irreps; irrep++ ){
159  if ( Isizes[ irrep ] > 0 ){
160  dgemm_( &notrans, &trans, &L, Isizes + irrep, Isizes + irrep, &one, molden[ irrep ], &L, unitary[ irrep ], Isizes + irrep, &set, product[ irrep ], &L );
161  }
162  }
163 
164  string line, part;
165 
166  std::ifstream inputfile( original.c_str() );
167  std::ofstream outputfile( output.c_str(), std::ofstream::trunc );
168 
169  // First go to the start of the orbital coefficient dump
170  bool stop = false;
171  string start = "[MO]";
172  do {
173  getline( inputfile,line );
174  outputfile << line << std::endl;
175  const int pos = line.find( start );
176  if ( pos != string::npos ){ stop = true; }
177  } while ( stop == false );
178 
179  inputfile.close();
180 
181  for ( int irrep = 0; irrep < num_irreps; irrep++ ){
182  for ( int orb = 0; orb < Isizes[ irrep ]; orb++ ){
183  outputfile << " Sym= " << SymmInfo.getIrrepName( irrep ) << std::endl;
184  outputfile << " Ene= N/A" << std::endl;
185  outputfile << " Spin= Restricted" << std::endl;
186  outputfile << " Occup= N/A" << std::endl;
187  for ( int cnt = 0; cnt < L; cnt++ ){
188  outputfile << cnt + 1 << " " << product[ irrep ][ cnt + L * orb ] << std::endl;
189  }
190  }
191  }
192 
193  outputfile.close();
194 
195 }
196 
197 
void print(const string original, const string output)
Multiply and print the new molden file.
Definition: Molden.cpp:152
bool setGroup(const int nGroup)
Set the group.
Definition: Irreps.cpp:50
void read_molden(const string filename)
Read a molden file.
Definition: Molden.cpp:68
int getNumberOfIrreps() const
Get the number of irreps for the currently activated group.
Definition: Irreps.cpp:94
void read_unitary(const string filename)
Read a unitary matrix.
Definition: Molden.cpp:146
static void read(const string filename, const int n_irreps, double **storage)
Read the DMRGSCFmatrix from disk.
void symm_psi2molpro(int *psi2molpro) const
Fill the array psi2molpro with the irrep conventions of molpro for the currently activated group...
Definition: Irreps.cpp:177
int getGroupNumber() const
Get the group number.
Definition: Irreps.cpp:66
string getGroupName() const
Get the name of the group.
Definition: Irreps.cpp:68
Molden(const int L, const int group, int *irrep_sizes)
Constructor.
Definition: Molden.cpp:33
~Molden()
Destructor.
Definition: Molden.cpp:53
string getIrrepName(const int irrepNumber) const
Get the name of the irrep with number irrepNumber of the activated group. The irrep with number 0 is ...
Definition: Irreps.cpp:110