00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: QMTimestep.h,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.41 $ $Date: 2019年01月17日 21:21:01 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * 00019 * The QMTimestep and Wavefunction classes. 00020 * The QMTimestep class stores and manages all quantm chemistry related 00021 * data that are timestep dependent. These include gradients, charges, 00022 * SCF energies. Most importantly we also consider wave function 00023 * trajectories which enables the user to visualize orbital dynamics. 00024 * (None of the other visualization tools I'm aware of can do that :-) 00025 * 00026 * Moreover, each timestep can have multiple different wave functions. 00027 * This is useful for UHF calculations where we have two sets of orbitals 00028 * with opposite spins or for calculations with multiple excited states. 00029 * The number of existing wave function may vary between frames. 00030 * So we could have, for instance, a coordinate trajectory with orbitals 00031 * defined only for the last frame. Another typical case would be to have 00032 * a canonical wavefunction for each frame but for the last frame there 00033 * exists an additional set of localized orbitals. 00034 * The number of orbitals present for a given wavefunction may also 00035 * differ from frame to frame. 00036 * 00037 * In order to identify a wavefunction throughout the trajectory we 00038 * assign a unique wavefunction ID that is based on its 'signature' 00039 * (type, spin, excitation, multiplicity and an optional info string). 00040 * A list with the signatures of all different wavefunction occuring 00041 * over the course of the trajectory is kept in the QMData class. 00042 * 00043 ***************************************************************************/ 00044 #ifndef QMTIMESTEP_H 00045 #define QMTIMESTEP_H 00046 00047 #include "QMData.h" 00048 00049 class Timestep; 00050 00051 class Wavefunction { 00052 friend class QMTimestep; 00053 int idtag; 00054 int type; 00055 int spin; 00056 int excitation; 00057 int multiplicity; 00059 int num_orbitals; 00061 int num_coeffs; 00063 char info[QMDATA_BUFSIZ]; 00065 double energy; 00069 float *wave_coeffs; 00072 float *orb_energies; 00073 float *occupancies; 00074 int *orb_ids; 00077 int *orb_id2index; 00079 int *orb_sort_map; 00081 public: 00082 Wavefunction(); 00083 Wavefunction(const Wavefunction& wf); 00084 Wavefunction(int numcoeffs, 00085 int numorbitals, 00086 const float *coeffs, 00087 const float *energies, 00088 const float *occ, 00089 const int *orbids, 00090 double _energy, 00091 int _idtag, 00092 int _type, 00093 int _spin, 00094 int _excitation, 00095 int _multiplicity, 00096 char *infostr); 00097 ~Wavefunction(); 00098 00099 Wavefunction& operator=(const Wavefunction& wf); 00100 00101 // Move the data over from the given wavefunction wf 00102 // and set the pointers in wf to NULL. 00103 // This avoids copying the arrays. 00104 void movefrom(Wavefunction& wf); 00105 00106 int get_num_orbitals() const { return num_orbitals; } 00107 int get_num_coeffs() const { return num_coeffs; } 00108 00110 const float* get_coeffs() { return wave_coeffs; } 00111 00113 const float* get_orbenergies() { return orb_energies; } 00114 00116 const float* get_occupancies() { return occupancies; } 00117 00119 const int* get_orbids() { return orb_ids; } 00120 00121 // const float* get_coeffs(int orb); 00122 00124 void set_coeffs(const float *wfn, int norbitals, int wavef_size); 00125 00127 void set_orbenergies(const float *energies, int norbitals); 00128 00130 void set_occupancies(const float *occupancies, int norbitals); 00131 00133 void set_orbids(const int *orbids, int norbitals); 00134 00135 //float get_coeff(int orb, int i); 00136 float get_orbitalenergy(int orb) const; 00137 00139 double get_energy() { return energy; } 00140 00142 int get_spin() { return spin; } 00143 00145 int get_excitation() { return excitation; } 00146 00148 int get_multiplicity() { return multiplicity; } 00149 00150 const char* get_info() { return info; } 00151 00153 int get_type() const { return type; } 00154 00156 void get_typestr(char *&typestr) const; 00157 00159 int get_homo() const; 00160 00162 int get_num_occupied_double() const; 00163 00165 int get_num_occupied_single() const; 00166 00167 00168 void density_matrix(float *(&P)) const; 00169 void density_matrix(const QMData *qmdata, int atom, float *(&D)) const; 00170 void population_matrix(const float *S, float *(&P)) const; 00171 void population_matrix(const QMData *qmdata, int atom, 00172 const float *S, float *(&P)) const; 00173 00178 void sort_wave_coefficients(QMData *qmdata); 00179 00180 void sort_orbitals(Wavefunction *previous_wavef); 00181 00182 private: 00186 void sort_incr(QMData *qmdata, int atom, int ishell, int comp, 00187 int first, int num); 00188 }; 00189 00191 class QMTimestep { 00192 private: 00193 int num_scfiter; 00194 int num_atoms; 00195 #if 0 00196 int wavef_size; 00197 00198 #endif 00199 int num_wavef; 00200 Wavefunction *wavef; 00201 00202 int num_idtags; 00203 // XXX (should be same as num_wavef) 00204 00205 int *wavef_id_map; 00206 00207 00208 00209 double *scfenergies; 00210 float *gradients; 00211 00212 int num_charge_sets; 00213 double *charges; 00214 int *chargetypes; 00215 00216 00217 public: 00218 QMTimestep(int natoms); 00219 QMTimestep(const QMTimestep& ts); 00220 ~QMTimestep(void); 00221 00223 int add_wavefunction(QMData *qmdata, 00224 int numcoeffs, 00225 int numorbitals, 00226 const float *coeffs, 00227 const float *energies, 00228 float *occupancies, 00229 const int *orbids, 00230 double energy, 00231 int type, 00232 int spin, 00233 int excitation, 00234 int multiplicity, 00235 const char *info, 00236 wavef_signa_t *(&signa_ts), 00237 int &num_signa_ts); 00238 00239 // Initialization functions 00240 void set_scfenergies(const double *energies, int numscfiter); 00241 void set_wavefunction(const float *wfn, int numorbitals, int num_gauss_basis_funcs); 00242 void set_orbitalenergies(const float *energies, int numorbitals); 00243 void set_gradients(const float *grad, int numatoms); 00244 00245 // Initialize the sets of atom charges. 00246 void set_charges(const double *q, const int *qtype, 00247 int numatoms, int numqsets); 00248 00250 void set_wavef_idtag(int iwave, int idtag); 00251 00253 Wavefunction* get_wavefunction(int iwave); 00254 00256 const float* get_wavecoeffs(int iwave); 00257 00259 const float* get_orbitalenergy(int iwave); 00260 00262 const float* get_occupancies(int iwave); 00263 00265 const int* get_orbitalids(int iwave); 00266 00268 const float* get_gradients() { return gradients; } 00269 00271 const double* get_scfenergies() { return scfenergies; } 00272 00274 const double* get_charge_set(int set); 00275 00277 int get_charge_type(int iset); 00278 00280 const char* get_charge_type_str(int iset); 00281 00283 int get_num_scfiter() { return num_scfiter; } 00284 00286 int get_num_charge_sets() { return num_charge_sets; } 00287 00289 int get_num_wavef() { return num_wavef; } 00290 00292 int get_num_coeffs(int iwave); 00293 00295 int get_num_orbitals(int iwave); 00296 00299 int get_wavef_index(int idtag); 00300 00303 int get_waveid(int iwave); 00304 00306 int get_spin(int iwave); 00307 00309 int get_excitation(int iwave); 00310 00312 int get_multiplicity(int iwave); 00313 00316 double get_wave_energy(int iwave); 00317 00318 // Get orbital index for HOMO 00319 int get_homo(int iwave); 00320 00321 // Get orbital index for LUMO 00322 int get_lumo(int iwave); 00323 00324 void get_orbital_occ_energy(int iwave, int orb, float &occ, float &energy); 00325 00326 // Get string describing the wavefunction type 00327 void get_wavef_typestr(int iwave, char *&typestr) { 00328 wavef[iwave].get_typestr(typestr); 00329 } 00330 00331 // Generate mapping that sorts the orbitals by similarity 00332 // throughout the trajectory (rather than by energy). 00333 // XXX Still unfinished. 00334 void sort_orbitals(QMTimestep *prev_qmts); 00335 00340 int get_orbital_id_from_index(int iwave, int index); 00341 00346 int get_orbital_index_from_id(int iwave, int id); 00347 00348 private: 00349 void sort_shell(QMData *qmdata, int atom, int ishell); 00350 void sort_incr(QMData *qmdata, int atom, int ishell, int comp, int first, int num); 00351 }; 00352 00356 void vmd_set_default_occ(float *(&occupancies), int scftyp, int numelec, int numorbitals, int multiplicity); 00357 00358 00359 #endif 00360