00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <ctype.h>
00029 #include <string.h>
00030 
00031 #include <string.h>
00032 
00033 #if defined(_AIX)
00034 #include <strings.h>
00035 #endif
00036 
00037 #if defined(WIN32) || defined(WIN64)
00038 #define strcasecmp stricmp
00039 #endif
00040 
00041 #include "molfile_plugin.h"
00042 #include "unit_conversion.h"
00043 #include "periodic_table.h"
00044 #include "qmplugin.h"
00045 
00046 
00047 #define ALLOCATE(array, type, size) \
00048   array = (type *)calloc(size, sizeof(type)); \
00049   if (array == NULL) { \
00050     fprintf(stderr, "moldenplugin) Memory allocation for %s failed!\n", #array); \
00051     return FALSE; \
00052   }
00053 
00054 #define GET_LINE(x,y) if (!fgets(x, sizeof(x), y)) return FALSE
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 typedef struct {
00065   long filepos_atoms;   
00066   long filepos_geomxyz; 
00067   long filepos_gto;     
00068   long filepos_mo;      
00069   char units[16];
00070   int coordsonly;
00071 } moldendata_t;
00072 
00073 
00074 
00075 
00076 static int get_basis (qmdata_t *);
00077 static int shelltype_int(char *type);
00078 static int fill_basis_arrays(qmdata_t *data);
00079 
00080 static int read_geom_block(qmdata_t *data);
00081 static int read_molecular_orbitals(qmdata_t *data);
00082 static int read_wave_coeffs(FILE *file, qm_wavefunction_t *wave);
00083 static int count_orbitals(qmdata_t *data);
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 static void *open_molden_read(const char *filename,
00105                               const char *filetype,
00106                               int *natoms) {
00107   FILE *fd;
00108   qmdata_t *data = NULL;
00109   moldendata_t *moldendata;
00110   char buffer[1024];
00111   char keystring[20];
00112 
00113   fd = fopen(filename, "rb");
00114   if (!fd) return NULL;
00115   
00116   
00117   data = init_qmdata();
00118   if (!data) return NULL;
00119 
00120   data->file = fd;
00121 
00122   
00123   moldendata = (moldendata_t *)calloc(1, sizeof(moldendata_t));
00124   if (!moldendata) return NULL;
00125 
00126   data->format_specific_data = moldendata;
00127 
00128 
00129   
00130   if (!fgets(buffer,1024,data->file)) return NULL;
00131 
00132   
00133   if (!strcmp(strtoupper(trimleft(trimright(buffer))), "[MOLDEN FORMAT]")) {
00134     printf("moldenplugin) Detected MOLDEN file format!\n");
00135   } else {
00136     printf("moldenplugin) The file is not in MOLDEN format!\n");
00137     return NULL;
00138   }
00139 
00140   eatwhitelines(data->file);
00141 
00142 
00143   
00144   while (fgets(buffer,1024,data->file)) {
00145 
00146     
00147     if (!sscanf(buffer, "%s", keystring)) continue;
00148 
00149     
00150     if (keystring[0]!='[') continue;
00151 
00152     
00153     strtoupper(keystring);
00154 
00155     if (!strcmp(keystring, "[5D]") || !strcmp(keystring, "[5D7F]") ||
00156         !strcmp(keystring, "[7F]") || !strcmp(keystring, "[5D10F]") ||
00157         !strcmp(keystring, "[9G]")) {
00158       printf("moldenplugin) Spherical harmonic basis found %s. \n", keystring);
00159       printf("moldenplugin)   Currently VMD handles only basis sets/wave functions\n");
00160       printf("moldenplugin)   with cartesian Gaussian functions.\n");
00161       printf("moldenplugin)   Loading coordinates only.\n");
00162       moldendata->coordsonly = 1;
00163     }
00164 
00165     if (!strcmp(keystring, "[ATOMS]")) {
00166       char *s;
00167       long prevline=ftell(fd);
00168       printf("moldenplugin) Found [ATOMS] section ...\n");
00169       moldendata->filepos_atoms = ftell(data->file);
00170 
00171       if (!sscanf(buffer, "%*s %s", moldendata->units)) {
00172         printf("moldenplugin) Missing units in [ATOMS] section!\n");
00173         return NULL;
00174       }
00175 
00176       
00177 
00178       
00179       (*natoms) = 0; 
00180       s = fgets(buffer, 1024, fd);
00181 
00182       
00183 
00184 
00185       while (trimleft(buffer)[0]!='[' && s!=NULL && !iswhiteline(buffer)) {
00186         (*natoms)++;
00187         prevline = ftell(fd);
00188         s = fgets(buffer, 1024, fd);
00189       }
00190       data->numatoms = *natoms;
00191       data->num_frames = 1;
00192 
00193       
00194 
00195       fseek(data->file, prevline, SEEK_SET);
00196     }
00197 
00198     else if (!strcmp(keystring, "[GEOMETRIES]")) {
00199       if (!strcmp(trimright(buffer), "[GEOMETRIES] XYZ")) {
00200         printf("moldenplugin) Found [GEOMETRIES] XYZ section ...\n");
00201 
00202         moldendata->filepos_geomxyz = ftell(data->file);
00203 
00204         
00205 
00206         if (fscanf(data->file, "%d", natoms) != 1) {
00207           printf("moldenplugin) No # atoms found in [GEOMETRIES] section!\n");
00208           return NULL;
00209         }
00210         data->numatoms = *natoms;
00211 
00212         
00213         fseek(data->file, moldendata->filepos_geomxyz, SEEK_SET);
00214 
00215         
00216         data->num_frames = 0;
00217         do {
00218           int natm = 0;
00219           fscanf(data->file, "%d", &natm);
00220           if (natm!=data->numatoms) break;
00221           eatline(data->file, 1);
00222 
00223           data->filepos_array = (long*)realloc(data->filepos_array,
00224                                                (data->num_frames+1)*sizeof(long));
00225           data->filepos_array[data->num_frames] = ftell(data->file);
00226 
00227           
00228           eatline(data->file, 1+data->numatoms);
00229           if (feof(data->file)) break;
00230 
00231           data->num_frames++;
00232         } while (1);
00233 
00234         printf("moldenplugin) Found %d frames\n", data->num_frames);
00235       } else if (!strcmp(trimright(buffer), "[GEOMETRIES] ZMAT")) {
00236         printf("moldenplugin) [GEOMETRIES] ZMAT not supported!\n");
00237       }
00238     }
00239 
00240     else if (!strcmp(keystring,"[GTO]")) {
00241       printf("moldenplugin) Found [GTO] section ...\n");
00242       moldendata->filepos_gto = ftell(data->file);
00243     }
00244 
00245     else if (!strcmp(keystring,"[MO]")) {
00246       printf("moldenplugin) Found [MO] section ...\n");
00247       moldendata->filepos_mo = ftell(data->file);
00248     }
00249 
00250   };
00251   
00252   return data;
00253 }
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 static int read_molden_structure(void *mydata, int *optflags, 
00270                                  molfile_atom_t *atoms) 
00271 {
00272   int i;
00273   char buffer[1024];
00274   char atname[1024];
00275   int num, atomicnum;
00276   molfile_atom_t *atom;
00277   qmdata_t *data = (qmdata_t *)mydata;
00278   moldendata_t *moldendata = (moldendata_t *)data->format_specific_data;
00279 
00280   ALLOCATE(data->atoms, qm_atom_t, data->numatoms);
00281 
00282   
00283 
00284   *optflags = MOLFILE_ATOMICNUMBER;
00285 
00286   
00287   if (moldendata->filepos_atoms) { 
00288     float unitfac = 1.f;
00289 
00290     
00291     
00292     if (!strcmp(moldendata->units, "AU") ||
00293         !strcmp(moldendata->units, "(AU)")) {
00294       unitfac = BOHR_TO_ANGS;
00295     }
00296     
00297     
00298     fseek(data->file, moldendata->filepos_atoms, SEEK_SET);
00299 
00300     
00301 
00302     for (i=0; i<data->numatoms; i++) {
00303       float x,y,z;
00304       atom = atoms+i;
00305       
00306       if (!fgets(buffer,1024,data->file)) return MOLFILE_ERROR;
00307       
00308       sscanf(buffer,"%s %d %d %f %f %f", atname, &num,
00309              &atomicnum, &x, &y, &z);
00310 
00311       
00312       strncpy(atom->name, atname,     sizeof(atom->name)); 
00313       strncpy(atom->type, atom->name, sizeof(atom->type));
00314       atom->atomicnumber = atomicnum;
00315       atom->resname[0] = '\0';
00316       atom->resid = 1;
00317       atom->chain[0] = '\0';
00318       atom->segid[0] = '\0';
00319 
00320       
00321       strncpy(data->atoms[i].type, atname, sizeof(data->atoms[i].type));
00322       data->atoms[i].atomicnum = atomicnum;
00323       data->atoms[i].x = x*unitfac;
00324       data->atoms[i].y = y*unitfac;
00325       data->atoms[i].z = z*unitfac;
00326     }
00327     data->num_frames_read = 1;
00328 
00329     return MOLFILE_SUCCESS;
00330   }
00331 
00332   
00333   if (moldendata->filepos_geomxyz) {
00334 
00335     
00336     fseek(data->file, moldendata->filepos_geomxyz, SEEK_SET);
00337     eatline(data->file, 2);
00338 
00339     
00340     for (i=0; i<data->numatoms; i++) {
00341       atom = atoms+i;
00342       if (!fgets(buffer,1024,data->file)) return MOLFILE_ERROR;
00343       sscanf(buffer,"%s %*f %*f %*f", atname);
00344 
00345       strncpy(atom->type, atname, sizeof(atom->type));
00346       strncpy(atom->name, atname, sizeof(atom->name)); 
00347       atom->atomicnumber = get_pte_idx_from_string(atname);
00348       atom->resname[0] = '\0';
00349       atom->resid = 1;
00350       atom->chain[0] = '\0';
00351       atom->segid[0] = '\0';
00352       data->atoms[i].atomicnum = atom->atomicnumber;
00353     }
00354     data->num_frames_read = 0;
00355 
00356     return MOLFILE_SUCCESS;
00357   }
00358 
00359   printf("Sorry, could not obtain structure information \n");
00360   printf("from either the [ATOMS] or [GEOMETRIES] section! \n");
00361   printf("Please check your MOLDEN output file! \n"); 
00362   return MOLFILE_ERROR; 
00363 }
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 static int read_geom_block(qmdata_t *data) {
00372   int i;
00373   char buffer[1024];
00374   float x,y,z;
00375 
00376   
00377   eatline(data->file, 1);
00378 
00379   for (i=0; i<data->numatoms; i++) {
00380     if (!fgets(buffer,1024,data->file)) return 0;
00381     sscanf(buffer,"%*s %f %f %f", &x, &y, &z);
00382     data->atoms[i].x = x;
00383     data->atoms[i].y = y;
00384     data->atoms[i].z = z;
00385   }
00386 
00387   return 1;
00388 }
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 static int read_timestep_metadata(void *mydata,
00398                                   molfile_timestep_metadata_t *meta) {
00399   meta->count = -1;
00400   meta->has_velocities = 0;
00401 
00402   return MOLFILE_SUCCESS;
00403 }
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 static int read_qm_timestep_metadata(void *mydata,
00413                                     molfile_qm_timestep_metadata_t *meta) {
00414   qmdata_t *data = (qmdata_t *)mydata;
00415   moldendata_t *moldendata = (moldendata_t *)data->format_specific_data;
00416 
00417   if (data->num_frames_sent >= data->num_frames) {
00418     
00419     return MOLFILE_ERROR;
00420   }
00421 
00422   
00423   if (moldendata->coordsonly) return MOLFILE_ERROR;
00424 
00425   
00426 
00427   if (data->num_frames_sent == data->num_frames-1) {
00428     int i;
00429     qm_timestep_t *cur_ts;
00430 
00431     if (!count_orbitals(data)) return MOLFILE_ERROR;
00432 
00433     
00434     cur_ts = data->qm_timestep;
00435     
00436     for (i=0; (i<MOLFILE_MAXWAVEPERTS && i<cur_ts->numwave); i++) {
00437       meta->num_orbitals_per_wavef[i] = cur_ts->wave[i].num_orbitals;
00438       meta->has_occup_per_wavef[i]    = cur_ts->wave[i].has_occup;
00439       meta->has_orben_per_wavef[i]    = cur_ts->wave[i].has_orben;
00440     }
00441     meta->wavef_size   = data->wavef_size;
00442     meta->num_wavef    = cur_ts->numwave;
00443     meta->num_scfiter  = cur_ts->num_scfiter;
00444     meta->has_gradient = FALSE;
00445     meta->num_charge_sets = 0;
00446   }
00447 
00448   return MOLFILE_SUCCESS;
00449 }
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 static int read_timestep(void *mydata, int natoms, 
00459        molfile_timestep_t *ts, molfile_qm_metadata_t *qm_metadata,
00460                          molfile_qm_timestep_t *qm_ts) {
00461   int i;
00462   qmdata_t *data = (qmdata_t *)mydata;
00463   qm_timestep_t *cur_ts;
00464 
00465   if (data->num_frames_sent >= data->num_frames) {
00466     
00467     return MOLFILE_ERROR;
00468   }
00469 
00470   if (data->num_frames_sent == data->num_frames_read) {
00471     
00472     fseek(data->file, data->filepos_array[data->num_frames_read], SEEK_SET);
00473     read_geom_block(data);
00474 
00475     
00476     data->num_frames_read++;
00477   }
00478 
00479 
00480   
00481   for (i=0; i<natoms; i++) {
00482     ts->coords[3*i  ] = data->atoms[i].x;
00483     ts->coords[3*i+1] = data->atoms[i].y;
00484     ts->coords[3*i+2] = data->atoms[i].z; 
00485   }
00486 
00487   
00488   data->num_frames_sent++;
00489 
00490   
00491   if (data->num_frames_sent == data->num_frames) {
00492 
00493     
00494     cur_ts = data->qm_timestep;
00495 
00496     read_molecular_orbitals(data);
00497 
00498     
00499     if (cur_ts != NULL && cur_ts->wave != NULL) {
00500       for (i=0; i<cur_ts->numwave; i++) {
00501         qm_wavefunction_t *wave = &cur_ts->wave[i];
00502         qm_ts->wave[i].type         = wave->type;
00503         qm_ts->wave[i].spin         = wave->spin;
00504         qm_ts->wave[i].excitation   = wave->exci;
00505         qm_ts->wave[i].multiplicity = wave->mult;
00506         qm_ts->wave[i].energy       = wave->energy;
00507         strncpy(qm_ts->wave[i].info, wave->info, MOLFILE_BUFSIZ);
00508         
00509         if (wave->wave_coeffs) {
00510           memcpy(qm_ts->wave[i].wave_coeffs, wave->wave_coeffs,
00511                  wave->num_orbitals*data->wavef_size*sizeof(float));
00512         }
00513         if (wave->orb_energies) {
00514           memcpy(qm_ts->wave[i].orbital_energies, wave->orb_energies,
00515                  wave->num_orbitals*sizeof(float));
00516         }
00517         if (wave->has_occup) {
00518           memcpy(qm_ts->wave[i].occupancies, wave->orb_occupancies,
00519                  wave->num_orbitals*sizeof(float));
00520         }
00521       }
00522     }
00523 
00524   }
00525 
00526   return MOLFILE_SUCCESS;
00527 }
00528   
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 static int read_molden_metadata(void *mydata, 
00543     molfile_qm_metadata_t *metadata) {
00544 
00545   qmdata_t *data;
00546   moldendata_t *moldendata;
00547   data = (qmdata_t *)mydata;
00548   moldendata = (moldendata_t *)data->format_specific_data;
00549 
00550 
00551   metadata->ncart = 0;
00552   metadata->nimag = 0;
00553   metadata->nintcoords = 0;
00554 
00555   metadata->have_sysinfo = 0;
00556   metadata->have_carthessian = 0;
00557   metadata->have_inthessian = 0;
00558   metadata->have_normalmodes = 0;
00559 
00560   metadata->num_basis_funcs = 0;
00561   metadata->num_basis_atoms = 0;
00562   metadata->num_shells = 0;
00563   metadata->wavef_size = 0;
00564 
00565   if (!moldendata->coordsonly) {
00566     
00567     if (!get_basis(data)) return MOLFILE_ERROR; 
00568 
00569     
00570     metadata->num_basis_funcs = data->num_basis_funcs;
00571     metadata->num_basis_atoms = data->num_basis_atoms;
00572     metadata->num_shells      = data->num_shells;
00573     metadata->wavef_size      = data->wavef_size;  
00574   }
00575 
00576   return MOLFILE_SUCCESS;
00577 }
00578 
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 static int read_molden_rundata(void *mydata, 
00588                                molfile_qm_t *qm_data) {
00589   qmdata_t *data = (qmdata_t *)mydata;
00590   int i;
00591   molfile_qm_hessian_t *hessian_data;
00592   molfile_qm_basis_t   *basis_data;
00593   molfile_qm_sysinfo_t *sys_data;
00594 
00595   if (!qm_data) return MOLFILE_ERROR;
00596 
00597 
00598   hessian_data = &qm_data->hess;
00599   basis_data   = &qm_data->basis;
00600   sys_data     = &qm_data->run;
00601 
00602   sys_data->num_electrons = data->num_electrons;
00603   sys_data->totalcharge = data->totalcharge;
00604 
00605   
00606   if (data->num_basis_funcs) {
00607     for (i=0; i<data->num_basis_atoms; i++) {
00608       basis_data->num_shells_per_atom[i] = data->num_shells_per_atom[i];
00609       basis_data->atomic_number[i] = data->atomicnum_per_basisatom[i];
00610     }
00611     
00612     for (i=0; i<data->num_shells; i++) {
00613       basis_data->num_prim_per_shell[i] = data->num_prim_per_shell[i];
00614       basis_data->shell_types[i] = data->shell_types[i];
00615     }
00616     
00617     for (i=0; i<2*data->num_basis_funcs; i++) {
00618       basis_data->basis[i] = data->basis[i];
00619     }
00620 
00621     
00622 
00623     if (data->angular_momentum) {
00624       for (i=0; i<3*data->wavef_size; i++) {
00625         basis_data->angular_momentum[i] = data->angular_momentum[i];
00626       }
00627     }
00628   }
00629 
00630   
00631   
00632 
00633 
00634 
00635 
00636 
00637 
00638 
00639 
00640   return MOLFILE_SUCCESS;
00641 }
00642 
00643 
00644 
00645 
00646 
00647 
00648 
00649 static void close_molden_read(void *mydata) {
00650   int i, j;
00651   qmdata_t *data = (qmdata_t *)mydata;
00652 
00653   fclose(data->file);
00654 
00655   free(data->atoms);
00656   free(data->basis);
00657   free(data->shell_types);
00658   free(data->atomicnum_per_basisatom);
00659   free(data->num_shells_per_atom);
00660   free(data->num_prim_per_shell);
00661   free(data->angular_momentum);
00662 
00663   if (data->basis_set) {
00664     for(i=0; i<data->num_basis_atoms; i++) {
00665       for (j=0; j<data->basis_set[i].numshells; j++) {
00666         free(data->basis_set[i].shell[j].prim);
00667       }
00668       free(data->basis_set[i].shell);
00669     } 
00670     free(data->basis_set);
00671   }
00672 
00673   free(data->format_specific_data);
00674   free(data->filepos_array);
00675 
00676   if (data->qm_timestep != NULL) {
00677     for (j=0; j<data->qm_timestep[0].numwave; j++) {
00678       free(data->qm_timestep[0].wave[j].wave_coeffs);
00679       free(data->qm_timestep[0].wave[j].orb_energies);
00680       free(data->qm_timestep[0].wave[j].orb_occupancies);
00681     }
00682     free(data->qm_timestep[0].wave);
00683     free(data->qm_timestep);
00684   } else {
00685     printf("close_molden_read(): NULL qm_timestep!\n");
00686   }
00687 
00688   free(data);
00689 }
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 
00736 
00737 
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 
00756 static int get_basis(qmdata_t *data) {
00757   char buffer[1024];
00758   char shelltype[1024];
00759   int atomid, numprims;
00760   int i, j=0;
00761   int numshells;
00762   moldendata_t *moldendata = (moldendata_t *)data->format_specific_data;
00763 
00764   
00765   data->num_shells = 0;
00766   data->num_basis_funcs = 0;
00767   data->num_basis_atoms = 0;
00768 
00769   
00770   memset(data->basis_string, 0, sizeof(data->basis_string));
00771 
00772 
00773   
00774   fseek(data->file, moldendata->filepos_gto, SEEK_SET);
00775  
00776   
00777   ALLOCATE(data->basis_set, basis_atom_t, data->numatoms);
00778 
00779   
00780   for (i=0; i<data->numatoms; i++) {
00781 
00782     if (!fgets(buffer,1024,data->file)) return FALSE;
00783     sscanf(buffer,"%d %*d", &atomid);
00784 
00785     numshells = 0;
00786     data->basis_set[i].shell = NULL;
00787 
00788     
00789     while (1) {
00790       shell_t *shell, *shell2=NULL;
00791 
00792       if (!fgets(buffer,1024,data->file)) return FALSE;
00793       
00794       
00795       if (!strlen(trimleft(buffer))) break;
00796       
00797       
00798       sscanf(buffer,"%s %d %*f", shelltype, &numprims);
00799 
00800 
00801       
00802       if (!strcasecmp(shelltype, "sp")) {
00803         
00804         data->basis_set[i].shell =
00805           (shell_t*)realloc(data->basis_set[i].shell,
00806                             (numshells+2)*sizeof(shell_t));
00807       } else {
00808         
00809         data->basis_set[i].shell =
00810           (shell_t*)realloc(data->basis_set[i].shell,
00811                             (numshells+1)*sizeof(shell_t));
00812       }
00813 
00814       shell  = &(data->basis_set[i].shell[numshells]);
00815       memset(shell, 0, sizeof(shell_t));
00816       shell->numprims = numprims;
00817       shell->type     = shelltype_int(shelltype);
00818       shell->prim     = (prim_t*)calloc(numprims, sizeof(prim_t));
00819 
00820       
00821 
00822       if (!strcasecmp(shelltype, "sp")) {
00823         shell->type      = SP_S_SHELL;
00824         shell2 = &(data->basis_set[i].shell[numshells+1]);
00825         shell2->numprims = numprims;
00826         shell2->type     = SP_P_SHELL;
00827         shell2->prim     = (prim_t*)calloc(numprims, sizeof(prim_t));
00828       }
00829 
00830       
00831       for (j=0; j<numprims; j++) {
00832         int nr;
00833         double expon=0.f, coeff1, coeff2=0.f;
00834         if (!fgets(buffer,1024,data->file)) return FALSE;
00835 
00836         
00837 
00838 
00839 
00840 
00841 
00842         fpexpftoc(buffer);
00843         nr = sscanf(buffer,"%lf %lf %lf", &expon, &coeff1, &coeff2);
00844         if (nr<2) {
00845           printf("moldenplugin) Bad format in [GTO] section\n");
00846           return FALSE;
00847         }
00848         shell->prim[j].exponent = expon;
00849         shell->prim[j].contraction_coeff = coeff1;
00850 
00851         
00852         if (!strcasecmp(shelltype, "sp")) {
00853           if (nr!=3) {
00854             printf("moldenplugin) Bad SP-shell format in [GTO] section\n");
00855             return FALSE;
00856           }
00857           shell2->prim[j].exponent = expon;
00858           shell2->prim[j].contraction_coeff = coeff2;
00859         }
00860       }
00861 
00862       
00863       data->num_basis_funcs += numprims;
00864 
00865       numshells++;
00866 
00867       
00868       if (!strcasecmp(shelltype, "sp")) {
00869         numshells++;
00870         data->num_basis_funcs += numprims;
00871       }
00872     }
00873 
00874     
00875     data->basis_set[i].numshells = numshells;
00876 
00877     
00878     data->num_shells += numshells;
00879   }
00880 
00881   
00882 
00883 
00884   data->num_basis_atoms = data->numatoms;
00885 
00886   
00887   fill_basis_arrays(data);
00888 
00889   
00890 
00891   data->wavef_size = 0;
00892   for (i=0; i<data->num_shells; i++) {
00893     switch (data->shell_types[i]) {
00894     case S_SHELL:
00895     case SP_S_SHELL:
00896       data->wavef_size += 1;
00897       break;
00898     case P_SHELL:
00899     case SP_P_SHELL:
00900       data->wavef_size += 3;
00901       break;
00902     case D_SHELL:
00903       data->wavef_size += 6;
00904       break;
00905     case F_SHELL:
00906       data->wavef_size += 10;
00907       break;
00908     case G_SHELL:
00909       data->wavef_size += 15;
00910       break;
00911     }
00912   }
00913 
00914   
00915 
00916 
00917 
00918 
00919 
00920 
00921 
00922 
00923 
00924 
00925 
00926 
00927 
00928   ALLOCATE(data->angular_momentum, int, 3*data->wavef_size);
00929 
00930   j=0;
00931   for (i=0; i<data->num_shells; i++) {
00932     switch (data->shell_types[i]) {
00933     case S_SHELL:
00934     case SP_S_SHELL:
00935       data->angular_momentum[j  ]=0;
00936       data->angular_momentum[j+1]=0;
00937       data->angular_momentum[j+2]=0;
00938       j += 3;
00939       break;
00940     case P_SHELL:
00941     case SP_P_SHELL:
00942       angular_momentum_expon(&data->angular_momentum[j  ], "x");
00943       angular_momentum_expon(&data->angular_momentum[j+3], "y");
00944       angular_momentum_expon(&data->angular_momentum[j+6], "z");
00945       j += 9;
00946       break;
00947     case D_SHELL:
00948       angular_momentum_expon(&data->angular_momentum[j   ], "xx");
00949       angular_momentum_expon(&data->angular_momentum[j+3 ], "yy");
00950       angular_momentum_expon(&data->angular_momentum[j+6 ], "zz");
00951       angular_momentum_expon(&data->angular_momentum[j+9 ], "xy");
00952       angular_momentum_expon(&data->angular_momentum[j+12], "xz");
00953       angular_momentum_expon(&data->angular_momentum[j+15], "yz");
00954       j += 18;
00955       break;
00956     case F_SHELL:
00957       angular_momentum_expon(&data->angular_momentum[j   ], "xxx");
00958       angular_momentum_expon(&data->angular_momentum[j+3 ], "yyy");
00959       angular_momentum_expon(&data->angular_momentum[j+6 ], "zzz");
00960       angular_momentum_expon(&data->angular_momentum[j+9 ], "xyy");
00961       angular_momentum_expon(&data->angular_momentum[j+12], "xxy");
00962       angular_momentum_expon(&data->angular_momentum[j+15], "xxz");
00963       angular_momentum_expon(&data->angular_momentum[j+18], "xzz");
00964       angular_momentum_expon(&data->angular_momentum[j+21], "yzz");
00965       angular_momentum_expon(&data->angular_momentum[j+24], "yyz");
00966       angular_momentum_expon(&data->angular_momentum[j+27], "xyz");
00967       j += 30;
00968       break;
00969     case G_SHELL:
00970       angular_momentum_expon(&data->angular_momentum[j   ], "xxxx");
00971       angular_momentum_expon(&data->angular_momentum[j+3 ], "yyyy");
00972       angular_momentum_expon(&data->angular_momentum[j+6 ], "zzzz");
00973       angular_momentum_expon(&data->angular_momentum[j+9 ], "xxxy");
00974       angular_momentum_expon(&data->angular_momentum[j+12], "xxxz");
00975       angular_momentum_expon(&data->angular_momentum[j+15], "yyyx");
00976       angular_momentum_expon(&data->angular_momentum[j+18], "yyyz");
00977       angular_momentum_expon(&data->angular_momentum[j+21], "zzzx");
00978       angular_momentum_expon(&data->angular_momentum[j+24], "zzzy");
00979       angular_momentum_expon(&data->angular_momentum[j+27], "xxyy");
00980       angular_momentum_expon(&data->angular_momentum[j+30], "xxzz");
00981       angular_momentum_expon(&data->angular_momentum[j+33], "yyzz");
00982       angular_momentum_expon(&data->angular_momentum[j+36], "xxyz");
00983       angular_momentum_expon(&data->angular_momentum[j+39], "yyxz");
00984       angular_momentum_expon(&data->angular_momentum[j+42], "zzxy");
00985       j += 45;
00986       break;
00987     }
00988   }
00989 
00990   return TRUE;
00991 }
00992 
00993 
00994 
00995 
00996 
00997 
00998 
00999 
01000 static int fill_basis_arrays(qmdata_t *data) {
01001   int i, j, k;
01002   int shellcount = 0;
01003   int primcount = 0;
01004 
01005   float *basis;
01006   int *num_shells_per_atom;
01007   int *num_prim_per_shell;
01008   int *shell_types;
01009   int *atomicnum_per_basisatom;
01010 
01011   
01012 
01013   for(i=0; i<data->num_basis_atoms; i++) {
01014     for (j=0; j<data->basis_set[i].numshells; j++) {
01015       primcount += data->basis_set[i].shell[j].numprims;
01016     }
01017   }
01018   data->num_basis_funcs = primcount;
01019 
01020   
01021 
01022 
01023 
01024 
01025 
01026 
01027 
01028   ALLOCATE(basis,                   float, 2*primcount);
01029   ALLOCATE(shell_types,             int,   data->num_shells);
01030   ALLOCATE(num_shells_per_atom,     int,   data->num_basis_atoms);
01031   ALLOCATE(num_prim_per_shell,      int,   data->num_shells);
01032   ALLOCATE(atomicnum_per_basisatom, int,   data->num_basis_atoms);
01033 
01034 
01035 
01036   
01037   data->basis = basis;
01038   data->shell_types = shell_types;
01039   data->num_shells_per_atom = num_shells_per_atom;
01040   data->num_prim_per_shell  = num_prim_per_shell;
01041   data->atomicnum_per_basisatom = atomicnum_per_basisatom;
01042 
01043   primcount = 0;
01044   for (i=0; i<data->num_basis_atoms; i++) {
01045     
01046     data->basis_set[i].atomicnum = data->atoms[i].atomicnum;
01047     atomicnum_per_basisatom[i]   = data->atoms[i].atomicnum;
01048 
01049     num_shells_per_atom[i] = data->basis_set[i].numshells;
01050 
01051     for (j=0; j<data->basis_set[i].numshells; j++) {
01052       shell_types[shellcount]        = data->basis_set[i].shell[j].type;
01053       num_prim_per_shell[shellcount] = data->basis_set[i].shell[j].numprims;
01054 
01055       for (k=0; k<data->basis_set[i].shell[j].numprims; k++) {
01056         basis[2*primcount  ] = data->basis_set[i].shell[j].prim[k].exponent;
01057         basis[2*primcount+1] = data->basis_set[i].shell[j].prim[k].contraction_coeff;
01058         primcount++;
01059       }
01060       shellcount++;
01061     }
01062   } 
01063 
01064   return TRUE;
01065 }
01066 
01067 
01068 
01069 
01070 
01071 
01072 
01073 
01074 
01075 static int shelltype_int(char *type) {
01076   int shelltype;
01077   if      (!strcasecmp(type, "sp")) shelltype = SP_SHELL;
01078   else if (!strcasecmp(type, "s"))  shelltype = S_SHELL;
01079   else if (!strcasecmp(type, "p"))  shelltype = P_SHELL;
01080   else if (!strcasecmp(type, "d"))  shelltype = D_SHELL;
01081   else if (!strcasecmp(type, "f"))  shelltype = F_SHELL;
01082   else if (!strcasecmp(type, "g"))  shelltype = G_SHELL;
01083   else shelltype = UNK_SHELL;
01084   
01085   return shelltype;
01086 }
01087 
01088 
01089 
01090 
01091 
01092 
01093 
01094 
01095 
01096 
01097 
01098 
01099 
01100 
01101 
01102 
01103 
01104 
01105 static int count_orbitals(qmdata_t *data) {
01106   int nr;
01107   int num_wave_coeff=0;
01108   float orbenergy, occu;
01109   char spin[1024];
01110   qm_wavefunction_t *wave;
01111   moldendata_t *moldendata = (moldendata_t *)data->format_specific_data;
01112   int dummy1;
01113   float dummy2;
01114 
01115   
01116   fseek(data->file, moldendata->filepos_mo, SEEK_SET);
01117   if (!goto_keyline(data->file, "Spin=", NULL)) {
01118     printf("moldenplugin) Couldn't find keyword 'Spin' in [MO] section!\n");
01119     return FALSE;
01120   }
01121  
01122   nr = fscanf(data->file, " Spin= %s\n", spin);
01123   eatline(data->file, 1);
01124 
01125   
01126   strtoupper(spin);
01127   if (strcmp(spin, "ALPHA")) return FALSE;
01128 
01129   
01130   num_wave_coeff = data->wavef_size;
01131 
01132   
01133   
01134 
01135 
01136 
01137 
01138 
01139 
01140 
01141 
01142 
01143 
01144   
01145   data->qm_timestep = (qm_timestep_t *)calloc(1, sizeof(qm_timestep_t));
01146 
01147   
01148   wave = add_wavefunction(data->qm_timestep);
01149 
01150   wave->spin = SPIN_ALPHA;
01151   wave->type = MOLFILE_WAVE_UNKNOWN;
01152   wave->exci = 0;
01153   wave->mult = 1;
01154   wave->num_coeffs = num_wave_coeff;
01155 
01156   
01157   fseek(data->file, moldendata->filepos_mo, SEEK_SET);
01158 
01159   
01160   fscanf(data->file, " Ene= %f\n", &orbenergy);
01161   fscanf(data->file, " Spin= %s\n", spin);
01162   fscanf(data->file, " Occup= %f\n", &occu);
01163 
01164   while (1) {
01165     int check_reads = 2;
01166     wave->num_orbitals++;
01167 
01168     
01169     while(check_reads == 2)
01170     {
01171       check_reads = fscanf(data->file, "%d %f", &dummy1, &dummy2);
01172     }
01173 
01174     nr  = fscanf(data->file, " Ene= %f\n", &orbenergy);
01175     nr += fscanf(data->file, " Spin= %s\n", spin);
01176     nr += fscanf(data->file, " Occup= %f\n", &occu);
01177 
01178     if (nr!=3 || toupper(spin[0])!='A') 
01179       break;
01180   }
01181   
01182 
01183 
01184   
01185   if (!strcmp(strtoupper(spin), "BETA")) {
01186     wave = add_wavefunction(data->qm_timestep);
01187     wave->spin = SPIN_BETA;
01188     wave->type = MOLFILE_WAVE_UNKNOWN;
01189     wave->exci = 0;
01190     wave->mult = 1;
01191     wave->num_coeffs = num_wave_coeff;
01192     wave->num_orbitals = 1;
01193 
01194     while (1) {
01195       int check_reads = 2;
01196       wave->num_orbitals++;
01197 
01198       
01199       while(check_reads == 2)
01200       {
01201         check_reads = fscanf(data->file, "%d %f", &dummy1, &dummy2);
01202       }
01203 
01204       nr  = fscanf(data->file, " Ene= %f\n", &orbenergy);
01205       nr += fscanf(data->file, " Spin= %s\n", spin);
01206       nr += fscanf(data->file, " Occup= %f\n", &occu);
01207 
01208       if (nr!=3 || toupper(spin[0])!='B' ||
01209           wave->num_orbitals>=num_wave_coeff) break;
01210     }
01211   }
01212 
01213   return TRUE;
01214 }
01215 
01216 
01217 static int read_molecular_orbitals(qmdata_t *data) {
01218   moldendata_t *moldendata = (moldendata_t *)data->format_specific_data;
01219   qm_wavefunction_t *wave;
01220 
01221   if (!data->qm_timestep || moldendata->coordsonly) return FALSE;
01222 
01223   
01224   fseek(data->file, moldendata->filepos_mo, SEEK_SET);
01225 
01226   wave = &data->qm_timestep->wave[0];
01227   ALLOCATE(wave->wave_coeffs, float, wave->num_coeffs*wave->num_orbitals);
01228   
01229   
01230 
01231 
01232 
01233 
01234   
01235 
01236   
01237   if (!read_wave_coeffs(data->file, wave)) return FALSE;
01238 
01239   if (data->qm_timestep->numwave==1) return TRUE;
01240 
01241   
01242   wave = &data->qm_timestep->wave[1];
01243   ALLOCATE(wave->wave_coeffs, float, wave->num_coeffs*wave->num_orbitals);
01244 
01245   if (!read_wave_coeffs(data->file, wave)) return FALSE;
01246 
01247   return TRUE;
01248 }
01249 
01250 static int read_wave_coeffs(FILE *file, qm_wavefunction_t *wave) {
01251   int i, j, nr;
01252   char buffer[1024];
01253   int AOid;
01254   float wf_coeff;
01255   char keystring[10];
01256   float *wave_coeffs = wave->wave_coeffs;
01257 
01258   
01259 
01260 
01261   
01262   for (i=0; i<wave->num_orbitals; i++)
01263     for (j=0; j<wave->num_coeffs; j++)
01264         wave_coeffs[i*wave->num_coeffs + j] = 0.0;
01265 
01266   
01267   
01268   eatline(file, 3);
01269   for (i=0; i<wave->num_orbitals; i++) {
01270     while(1) {
01271       int nr2;
01272       if (!fgets(buffer,1024,file)) return FALSE;
01273       nr = sscanf(buffer,"%d %f", &AOid, &wf_coeff);
01274       wave_coeffs[i*wave->num_coeffs+AOid-1] = wf_coeff;
01275       
01276       
01277       
01278       nr2 = sscanf(buffer, "%s", keystring);
01279       if(!strcmp(keystring,"Ene=")||nr2==-1) 
01280         break;
01281 
01282       if (nr==0) {
01283         printf("moldenplugin) Error reading wavefunction coefficients!\n");
01284         return FALSE;
01285       }
01286     }
01287     eatline(file, 2);
01288   }
01289   return TRUE;
01290 }
01291 
01292 
01293 
01294 
01295 
01296 
01297 static molfile_plugin_t plugin;
01298 
01299 VMDPLUGIN_API int VMDPLUGIN_init() {
01300   memset(&plugin, 0, sizeof(molfile_plugin_t));
01301   plugin.abiversion = vmdplugin_ABIVERSION;
01302   plugin.type = MOLFILE_PLUGIN_TYPE;
01303   plugin.name = "molden";
01304   plugin.prettyname = "Molden";
01305   plugin.author = "Markus Dittrich, Jan Saam, Alexey Titov";
01306   plugin.majorv = 0;
01307   plugin.minorv = 10;
01308   plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
01309   plugin.filename_extension = "molden";
01310   plugin.open_file_read = open_molden_read;
01311   plugin.read_structure = read_molden_structure;
01312 
01313   plugin.read_timestep_metadata    = read_timestep_metadata;
01314   plugin.read_timestep             = read_timestep;
01315   plugin.read_qm_timestep_metadata = read_qm_timestep_metadata;
01316 
01317   plugin.read_qm_metadata = read_molden_metadata;
01318   plugin.read_qm_rundata  = read_molden_rundata;
01319 
01320   plugin.close_file_read = close_molden_read;
01321   return VMDPLUGIN_SUCCESS;
01322 }
01323 
01324 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
01325   (*cb)(v, (vmdplugin_t *)&plugin);
01326   return VMDPLUGIN_SUCCESS;
01327 }
01328 
01329 VMDPLUGIN_API int VMDPLUGIN_fini() {
01330   return VMDPLUGIN_SUCCESS;
01331 }
01332