Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

QMData.h

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 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: QMData.h,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.85 $       $Date: 2010/12/16 04:08:36 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * The QMData class, which stores all QM calculation data that
00020  * are not dependent on the timestep (the latter are handled by
00021  * the QMTimestep class).
00022  * These data are, for instance, basis set and calculation input
00023  * parameters such as method and multiplicity.
00024  * Note that the wavefunctions are stored in QMTimestep but that
00025  * a signature of all wavefunctions that occur in the trajectory
00026  * is kept here in QMData. The signature is needed for setting up
00027  * the Orbital representation GUI. 
00028  *
00029  * Basis set storage
00030  * -----------------
00031  * The basis set data are stored in hierarchical data structures
00032  * for convenient access and better readability of the non 
00033  * performance critical code. However, the actual orbital
00034  * computation (performed by the Orbital class) needs simple
00035  * contiguous arrays which is why we keep those too. Since we
00036  * have only one basis set per molecule this redundant storage
00037  * should not be too memory demanding.
00038  *
00039  * Basis set normalization
00040  * -----------------------
00041  * The general functional form of a normalized Gaussian-type
00042  * orbital basis function in cartesian coordinates is:
00043  *
00044  * Phi_GTO(x,y,z;a,i,j,k) = (2a/pi)^(3/4) * sqrt[(8a)^L]
00045  *          * sqrt[i!j!k!/((2i)!(2j)!(2k)!)]
00046  *          * x^i * y^j * z^k * exp[-a(x^2+y^2+z^2)]
00047  *
00048  * where x,y,z are the coordinates, a is the primitive exponent
00049  * and i,j,k are non-negative integers controlling the cartesian
00050  * shape of the GTO. For instance:
00051  * S  -> (0,0,0)
00052  * Px -> (1,0,0)
00053  * Py -> (0,1,0)
00054  * Dxx-> (2,0,0)
00055  * L=i+j+k denotes the shell type with L={0,1,2,3,...} for
00056  * {S,P,D,F,...} shells.
00057  * The contracted GTO is then defined by a linear combination of
00058  * GTO primitives
00059  *
00060  * Phi_CGTO = sum[c_p * Phi_GTO(x,y,z;a_p,i,j,k)]
00061  *
00062  * where c_p and a_p are the contraction coefficient and the
00063  * exponent for primitive p.
00064  *
00065  * The 3rd line in the expression for Phi_GTO is the actual
00066  * basis function while the first line shell-type dependent part
00067  * of the normalization factor and the second line comprises the 
00068  * angular momentum dependent part of the normalization.
00069  *
00070  * Finally, the wavefunction Psi for an orbital is a linear
00071  * combination of contracted basis functions Phi_CGTO.
00072  *
00073  * Psi = sum[c_k*Phi_CGTO_k]
00074  *
00075  * I.e. each wavefunction coefficient c_k must be multiplied with
00076  * the corresponding Phi_CGTO_k.
00077  *
00078  * Conceptionally it would be straightforward to just generate
00079  * an array with all Phi_CGTO_k. But for a high performance
00080  * implementation where fast memory is precious (e.g. constant
00081  * memory on GPUs) this is not efficient, especially for basis
00082  * sets with a large number of primitives per shell.
00083  * We have only one pair of contraction coefficient and exponent
00084  * per primitive but several cartesian components such as
00085  * Px, Py, Pz. Hence, we can multiply the shell dependent part
00086  * of the normalization factor into the contraction coefficient.
00087  * This is done in normalize_basis() which is called at the end
00088  * of init_basis(). For the angular momentum dependent part we
00089  * create a lookup table in init_angular_norm_factors() which 
00090  * is factored into the wavefunction coefficients when an Orbital
00091  * object is created for rendering purpose.
00092  *
00093  ***************************************************************************/
00094 #ifndef QMDATA_H
00095 #define QMDATA_H
00096 
00097 
00098 #define GUI_WAVEF_TYPE_CANON    0
00099 #define GUI_WAVEF_TYPE_GEMINAL  1
00100 #define GUI_WAVEF_TYPE_MCSCFNAT 2
00101 #define GUI_WAVEF_TYPE_MCSCFOPT 3
00102 #define GUI_WAVEF_TYPE_CINAT    4
00103 #define GUI_WAVEF_TYPE_LOCAL    5
00104 #define GUI_WAVEF_TYPE_OTHER    6
00105 
00106 #define GUI_WAVEF_SPIN_ALPHA    0
00107 #define GUI_WAVEF_SPIN_BETA     1
00108 
00109 #define GUI_WAVEF_EXCI_GROUND   0
00110 
00111 // NOTE: this has to be kept in sync with the corresponding table
00112 //       in the QM molfile plugin reader. 
00113 // XXX   These should all be added to the molfile_plugin header
00114 //       When copied from the plugin to the internal data structure,
00115 //       we can either arrange that the molfile plugin constants and these
00116 //       are always identical, or we can use a switch() block to translate 
00117 //       between them if they ever diverge.
00118 #define SPD_D_SHELL -5
00119 #define SPD_P_SHELL -4
00120 #define SPD_S_SHELL -3
00121 #define SP_S_SHELL  -2
00122 #define SP_P_SHELL  -1
00123 #define S_SHELL      0
00124 #define P_SHELL      1
00125 #define D_SHELL      2
00126 #define F_SHELL      3
00127 #define G_SHELL      4
00128 #define H_SHELL      5
00129 #define I_SHELL      6
00130 
00131 #define QMDATA_BUFSIZ       81   
00132 #define QMDATA_BIGBUFSIZ  8192   
00133 
00134 // forward declarations.
00135 class Orbital;
00136 class QMTimestep;
00137 class Timestep;
00138 class Molecule;
00139 
00141 enum {
00142   QMSTATUS_UNKNOWN        = -1, // don't know
00143   QMSTATUS_OPT_CONV       =  0, // optimization converged
00144   QMSTATUS_SCF_NOT_CONV   =  1, // SCF convergence failed
00145   QMSTATUS_OPT_NOT_CONV   =  2, // optimization not converged
00146   QMSTATUS_FILE_TRUNCATED =  3  // file was truncated
00147 };
00148 
00150 enum {
00151   SCFTYPE_UNKNOWN = -1, // we have no info about the method used
00152   SCFTYPE_NONE    =  0, // calculation didn't make use of SCF at all
00153   SCFTYPE_RHF     =  1, // Restricted Hartree-Fock
00154   SCFTYPE_UHF     =  2, // unrestricted Hartree-Fock
00155   SCFTYPE_ROHF    =  3, // restricted open-shell Hartree-Fock
00156   SCFTYPE_GVB     =  4, // generalized valence bond orbitals
00157   SCFTYPE_MCSCF   =  5, // multi-configuration SCF
00158   SCFTYPE_FF      =  6  // classical force-field based sim.
00159 };
00160 
00162 enum {
00163   RUNTYPE_UNKNOWN    = 0,
00164   RUNTYPE_ENERGY     = 1, // single point energy evaluation
00165   RUNTYPE_OPTIMIZE   = 2, // geometry optimization
00166   RUNTYPE_SADPOINT   = 3, // saddle point search
00167   RUNTYPE_HESSIAN    = 4, // Hessian/frequency calculation
00168   RUNTYPE_SURFACE    = 5, // potential surface scan
00169   RUNTYPE_GRADIENT   = 6, // energy gradient calculation
00170   RUNTYPE_MEX        = 7, // minimum energy crossing
00171   RUNTYPE_DYNAMICS   = 8, // Any type of molecular dynamics
00172                           // e.g. Born-Oppenheimer, Car-Parinello,
00173                           // or classical MD
00174   RUNTYPE_PROPERTIES = 9  // Properties were calculated from a
00175                           // wavefunction that was read from file
00176 };
00177 
00179 enum {
00180   QMCHARGE_UNKNOWN  = 0, 
00181   QMCHARGE_MULLIKEN = 1, // Mulliken charges
00182   QMCHARGE_LOWDIN   = 2, // Lowdin charges
00183   QMCHARGE_ESP      = 3, // elstat. potential fitting
00184   QMCHARGE_NPA      = 4  // natural population analysis
00185 };
00186 
00187 
00215 enum {
00216   WAVE_CANON,    WAVE_GEMINAL, WAVE_MCSCFNAT,
00217   WAVE_MCSCFOPT, WAVE_CINATUR,
00218   WAVE_PIPEK,    WAVE_BOYS,    WAVE_RUEDEN,
00219   WAVE_NAO,      WAVE_PNAO,    WAVE_NHO, 
00220   WAVE_PNHO,     WAVE_NBO,     WAVE_PNBO, 
00221   WAVE_PNLMO,    WAVE_NLMO,    WAVE_MOAO, 
00222   WAVE_NATO,     WAVE_UNKNOWN
00223 };
00224 
00225 
00226 // Signature of a wavefunction, used to identify
00227 // a wavefunction thoughout the trajectory.
00228 // The orbital metadata are needed by the GUI to
00229 // determine what is the union of orbitals showing up
00230 // over the trajetory. It is displayed as the available
00231 // orbital list in the representations window.
00232 typedef struct {
00233   int type;
00234   int spin;
00235   int exci;
00236   char info[QMDATA_BUFSIZ];
00237 
00238   int max_avail_orbs; // maximum number of available orbitals
00239                       // over all frames.
00240   int *orbids;        // list of existing orbital IDs
00241   float *orbocc;      // occupancies of all available orbitals
00242 } wavef_signa_t;
00243 
00244 
00245 // Basis set data structures
00246 // -------------------------
00247 
00249 typedef struct {
00250   float expon;       
00251   float coeff;       
00252 } prim_t;
00253 
00255 typedef struct {
00256   int numprims;      
00257   int type;          
00258   int combo;         
00259 
00260 
00261   int num_cart_func; 
00262 
00263 
00264 
00265   float *norm_fac;   
00266   float *basis;      
00267   prim_t *prim;      
00268 } shell_t;
00269 
00271 typedef struct {
00272   int atomicnum;     
00273   int numshells;     
00274   shell_t *shell;    
00275 } basis_atom_t;
00276 
00279 class QMData {
00280  public:
00281   // Orbital data
00282   int num_wave_f;    
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290   int num_basis;     
00291 
00292 
00293 
00294   int num_wavef_signa; 
00295 
00296 
00297  private:
00298   int num_types;     
00299   int num_atoms;     
00300 
00301   int *atom_types;          
00302   int *atom_sort;           
00303   int *num_shells_per_atom; 
00304 
00305   int *wave_offset;         
00306 
00307 
00308 
00309 
00310 
00311   int num_shells;           
00312   int *num_prim_per_shell;  
00313 
00314   int *angular_momentum;    
00315 
00316 
00317 
00318 
00319   int highest_shell;        
00320 
00321 
00322   float **norm_factors;     
00323 
00324 
00325 
00326 
00327 
00328 
00329   float *basis_array;       
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341   int *atom_basis;          
00342 
00343   int *shell_types;         
00344 
00345 
00346 
00347 
00348 
00349 
00350   basis_atom_t *basis_set;  
00351 
00352 
00353 
00354 
00355 
00356 
00357   
00358 
00359   wavef_signa_t *wavef_signa; 
00360 
00361 
00362 
00363   // Hessian and frequency data.
00364   // These are actually timestep dependent but in almost all practical
00365   // cases they are just printed for the last step at the end of a 
00366   // calculation. 
00367   int nimag;                
00368   int nintcoords;           
00369 
00370   double *carthessian;     
00371 
00372 
00373   double *inthessian;      
00374 
00375 
00376   float *wavenumbers;      
00377   float *intensities;      
00378   float *normalmodes;      
00379   int   *imagmodes;        
00380 
00381 
00382 public:
00383   // QM run info
00384   int runtype;             
00385   int scftype;             
00386   int status;              
00387   int nproc;               
00388   int memory;              
00389   int num_electrons;       
00390   int totalcharge;         
00391   //int num_orbitals_A;      ///< number of alpha orbitals
00392   //int num_orbitals_B;      ///< number of beta orbitals
00393 
00394   char *basis_string;                  
00395   char runtitle[QMDATA_BIGBUFSIZ];     
00396   char geometry[QMDATA_BUFSIZ];        
00397 
00398   char version_string[QMDATA_BUFSIZ];  
00399 
00400 
00401   QMData(int natoms, int nbasis, int shells, int nwave); 
00402   ~QMData(void);                       
00403 
00404 
00407   void init_electrons(Molecule *mol, int totcharge);
00408 
00409 
00410   // ====================================
00411   // Functions for basis set initializion
00412   // ====================================
00413 
00415   void delete_basis_set();
00416 
00419   int init_basis(Molecule *mol, int num_basis_atoms, const char *string,
00420                  const float *basis, const int *atomic_numbers,
00421                  const int *nshells, const int *nprim,
00422                  const int *shelltypes);
00423 
00426   int create_unique_basis(Molecule *mol, int num_basis_atoms);
00427 
00430   void normalize_basis();
00431 
00432 #if 0                           // XXX: unused
00433 
00434   void sort_atoms_by_type();
00435 #endif
00436 
00439   void init_angular_norm_factors();
00440 
00441 
00442   // =================
00443   // Basis set acccess
00444   // =================
00445 
00447   const basis_atom_t* get_basis(int atom=0) const;
00448 
00450   const shell_t*      get_basis(int atom, int shell) const;
00451 
00452   const int* get_atom_types()          const { return atom_types; }
00453   const int* get_num_shells_per_atom() const { return num_shells_per_atom; }
00454   const int* get_num_prim_per_shell()  const { return num_prim_per_shell; }
00455 
00456   int get_num_atoms()                { return num_atoms; }
00457   int get_num_types()                { return num_types; }
00458   int get_num_shells()               { return num_shells; }
00459   int get_num_wavecoeff_per_atom(int atom) const;
00460 
00462   int get_wave_offset(int atom, int shell=0) const;
00463 
00465   const char* get_shell_type_str(const shell_t *shell);
00466 
00467   char* get_angular_momentum_str(int atom, int shell, int mom) const;
00468   void  set_angular_momentum_str(int atom, int shell, int mom,
00469                                  const char *tag);
00470   void  set_angular_momentum(int atom, int shell, int mom,
00471                              int *pow);
00472   int   get_angular_momentum(int atom, int shell, int mom, int comp);
00473   int   set_angular_momenta(const int *angmom);
00474 
00475 
00476   // ========================
00477   // Hessian and normal modes
00478   // ========================
00479 
00480   int get_num_imag()       { return nimag; }
00481   int get_num_intcoords()  { return nintcoords; }
00482   void set_carthessian(int numcartcoords, double *array);
00483   void set_inthessian(int numintcoords, double *array);
00484   void set_normalmodes(int numcart, float *array);
00485   void set_wavenumbers(int numcart, float *array);
00486   void set_intensities(int numcart, float *array);
00487   void set_imagmodes(int numimag, int *array);
00488   const double* get_carthessian() const { return carthessian; }
00489   const double* get_inthessian()  const { return inthessian;  }
00490   const float*  get_normalmodes() const { return normalmodes; }
00491   const float*  get_wavenumbers() const { return wavenumbers; }
00492   const float*  get_intensities() const { return intensities; }
00493   const int*    get_imagmodes()   const { return imagmodes;   }
00494 
00495 
00496   // =====================
00497   // Calculation meta data
00498   // =====================
00499 
00501   const char *get_scftype_string(void) const;
00502 
00504   const char *get_runtype_string(void) const;
00505   
00507   const char* get_status_string();
00508 
00509 
00510   // =======================
00511   // Wavefunction signatures
00512   // =======================
00513 
00516   int assign_wavef_id(int type, int spin, int excit, char *info,
00517                       wavef_signa_t *(&signa_ts), int &numsig);
00518 
00522   int find_wavef_id_from_gui_specs(int type, int spin, int exci);
00523 
00525   int compare_wavef_guitype_to_type(int guitype, int type);
00526 
00528   int has_wavef_guitype(int guitype);
00529 
00531   int has_wavef_spin(int spin);
00532 
00534   int has_wavef_exci(int exci);
00535 
00538   int has_wavef_signa(int type, int spin, int exci);
00539 
00542   int get_highest_excitation(int guitype);
00543 
00544 
00545   // ========================================================
00546   // Functions dealing with the list of orbitals available 
00547   // for a given wavefunction. Needed for the GUI.
00548   // ========================================================
00549 
00551   void update_avail_orbs(int iwavesig, int norbitals,
00552                          const int *orbids, const float *orbocc);
00553 
00559   int get_max_avail_orbitals(int iwavesig);
00560 
00564   int get_avail_orbitals(int iwavesig, int *(&orbids));
00565 
00568   int get_avail_occupancies(int iwavesig, float *(&orbocc));
00569 
00573   int get_orbital_label_from_gui_index(int iwavesig, int iorb);
00574 
00577   int has_orbital(int iwavesig, int orbid);
00578 
00579 #define ANGS_TO_BOHR 1.88972612478289694072f
00580 
00581   int expand_atompos(const float *atompos,
00582                      float *(&expandedpos));
00583   int expand_basis_array(float *(&expandedbasis), int *(&numprims));
00584 
00585   void compute_overlap_integrals(Timestep *ts,
00586                         const float *expandedbasis,
00587                         const int *numprims, float *(&overlap_matrix));
00588 
00589   int mullikenpop(Timestep *ts, int iwavesig, 
00590                   const float *expandedbasis,
00591                   const int *numprims);
00592 
00593 
00594   double localization_orbital_change(int orbid1, int orbid2,
00595                                         const float *C,
00596                                         const float *S);
00597 
00598   float pair_localization_measure(int num_orbitals,
00599                                   int orbid1, int orbid2,
00600                                   const float *C, const float *S);
00601 
00602   double mean_localization_measure(int num_orbitals, const float *C,
00603                                   const float *S);
00604 
00607   void rotate_2x2_orbitals(float *C, int orbid1, int orbid2,
00608                            double gamma);
00609 
00612   double localization_rotation_angle(const float *C, const float *S,
00613                                     int orbid1, int orbid2);
00614 
00615   // Return the gross Mulliken population of orbital i on atom A
00616   double gross_atom_mulliken_pop(const float *C, const float *S,
00617                                 int atom, int orbid) const;
00618 
00619   double orb_pair_gross_atom_mulliken_pop(const float *C, const float *S,
00620                                      int atom, int orbid1, int orbid2);
00621 
00624   int orblocalize(Timestep *ts, int waveid, const float *expandedbasis, 
00625                   const int *numprims);
00626 
00629   Orbital* create_orbital(int iwave, int orbid, float *pos,
00630                           QMTimestep *qmts);
00631 
00632 };
00633 
00634 
00635 
00636 #endif
00637 

Generated on Wed May 22 01:49:00 2013 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002