From eff8d7d8c74c9099b73566d9e03cf84697b5920b Mon Sep 17 00:00:00 2001 From: sjplimp Date: Wed, 13 Jun 2012 16:32:54 +0000 Subject: [PATCH] git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@8277 f3b2605a-c512-4ea7-a41b-209d697bcdaa --- src/FLD/pair_lubricate.cpp | 1 - src/FLD/pair_lubricate_poly.cpp | 1 - src/Makefile | 5 +- src/USER-MOLFILE/Install.sh | 44 + src/USER-MOLFILE/Package.sh | 13 + src/USER-MOLFILE/README | 24 + src/USER-MOLFILE/dump_molfile.cpp | 461 +++++++++++ src/USER-MOLFILE/dump_molfile.h | 105 +++ src/USER-MOLFILE/molfile_interface.cpp | 1052 ++++++++++++++++++++++++ src/USER-MOLFILE/molfile_interface.h | 158 ++++ src/USER-MOLFILE/molfile_plugin.h | 891 ++++++++++++++++++++ src/USER-MOLFILE/vmdplugin.h | 191 +++++ 12 files changed, 2942 insertions(+), 4 deletions(-) create mode 100644 src/USER-MOLFILE/Install.sh create mode 100644 src/USER-MOLFILE/Package.sh create mode 100644 src/USER-MOLFILE/README create mode 100644 src/USER-MOLFILE/dump_molfile.cpp create mode 100644 src/USER-MOLFILE/dump_molfile.h create mode 100644 src/USER-MOLFILE/molfile_interface.cpp create mode 100644 src/USER-MOLFILE/molfile_interface.h create mode 100644 src/USER-MOLFILE/molfile_plugin.h create mode 100644 src/USER-MOLFILE/vmdplugin.h diff --git a/src/FLD/pair_lubricate.cpp b/src/FLD/pair_lubricate.cpp index 4da0b28dc5..570f6b4eed 100755 --- a/src/FLD/pair_lubricate.cpp +++ b/src/FLD/pair_lubricate.cpp @@ -29,7 +29,6 @@ #include "neigh_list.h" #include "neigh_request.h" #include "domain.h" -#include "update.h" #include "modify.h" #include "fix.h" #include "fix_deform.h" diff --git a/src/FLD/pair_lubricate_poly.cpp b/src/FLD/pair_lubricate_poly.cpp index 168b6e8285..cb4e65d5a2 100644 --- a/src/FLD/pair_lubricate_poly.cpp +++ b/src/FLD/pair_lubricate_poly.cpp @@ -30,7 +30,6 @@ #include "neigh_list.h" #include "neigh_request.h" #include "domain.h" -#include "update.h" #include "modify.h" #include "fix.h" #include "fix_deform.h" diff --git a/src/Makefile b/src/Makefile index 457a72518a..1724ed0e72 100755 --- a/src/Makefile +++ b/src/Makefile @@ -18,10 +18,11 @@ PACKAGE = asphere class2 colloid dipole fld gpu granular kim \ shock srd xtc PACKUSER = user-misc user-atc user-awpmd user-cg-cmm user-colvars \ - user-cuda user-eff user-ewaldn user-omp \ + user-cuda user-eff user-ewaldn user-omp user-molfile \ user-reaxc user-sph -PACKLIB = gpu kim meam poems reax user-atc user-awpmd user-colvars user-cuda +PACKLIB = gpu kim meam poems reax user-atc user-awpmd user-colvars \ + user-cuda user-molfile PACKALL = $(PACKAGE) $(PACKUSER) diff --git a/src/USER-MOLFILE/Install.sh b/src/USER-MOLFILE/Install.sh new file mode 100644 index 0000000000..e17675201a --- /dev/null +++ b/src/USER-MOLFILE/Install.sh @@ -0,0 +1,44 @@ +# Install/unInstall package files in LAMMPS + +if (test $1 = 1) then + + if (test -e ../Makefile.package) then + sed -i -e 's/[^ \t]*molfile[^ \t]* //' ../Makefile.package + sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(molfile_SYSINC) |' ../Makefile.package + sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(molfile_SYSLIB) |' ../Makefile.package + sed -i -e 's|^PKG_SYSPATH =[ \t]*|&$(molfile_SYSPATH) |' ../Makefile.package + fi + + if (test -e ../Makefile.package.settings) then + sed -i -e '/^include.*molfile.*$/d' ../Makefile.package.settings + sed -i '4 i include ..\/..\/lib\/molfile\/Makefile.lammps' ../Makefile.package.settings + fi + + cp molfile_interface.cpp .. + cp dump_molfile.cpp .. + + cp molfile_interface.h .. + cp dump_molfile.h .. + + cp molfile_plugin.h .. + cp vmdplugin.h .. + +elif (test $1 = 0) then + + if (test -e ../Makefile.package) then + sed -i -e 's/[^ \t]*molfile[^ \t]* //' ../Makefile.package + fi + + if (test -e ../Makefile.package.settings) then + sed -i -e '/^include.*molfile.*$/d' ../Makefile.package.settings + fi + + rm -f ../molfile_interface.cpp + rm -f ../dump_molfile.cpp + + rm -f ../molfile_interface.h + rm -f ../dump_molfile.h + + rm -f ../molfile_plugin.h + rm -f ../vmdplugin.h +fi diff --git a/src/USER-MOLFILE/Package.sh b/src/USER-MOLFILE/Package.sh new file mode 100644 index 0000000000..a8b80b05a7 --- /dev/null +++ b/src/USER-MOLFILE/Package.sh @@ -0,0 +1,13 @@ +# Update package files in LAMMPS +# copy package file to src if it doesn't exists or is different +for file in molfile_interface.cpp molfile_interface.h molfile_plugin.h \ + dump_molfile.cpp dump_molfile.h vmdplugin.h ; do \ + if (test ! -e ../$file) then + echo " creating src/$file" + cp $file .. + elif ! cmp -s $file ../$file ; then + echo " updating src/$file" + cp $file .. + fi +done + diff --git a/src/USER-MOLFILE/README b/src/USER-MOLFILE/README new file mode 100644 index 0000000000..76363db171 --- /dev/null +++ b/src/USER-MOLFILE/README @@ -0,0 +1,24 @@ +This package provides an C++ interface class to the VMD molfile +plugins, http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/, and a +set of LAMMPS classes that use this interface. + +Molfile plugins provide a consistent programming interface to read and +write file formats commonly used in molecular simulations. The +package only provides the interface code, not the plugins; these can +be obtained from a VMD installation which has to match the platform +that you are using to compile LAMMPS for. By adding plugins, support +for new file formats can be added to LAMMPS (or VMD or other programs +that use them) without having to recompile the application itself. +The plugins are installed in the directory: +/plugins//molfile + +NOTE: while the programming interface (API) to the plugins is backward +compatible, the binary interface (ABI) has been changing over time, so +it is necessary to compile this package with the plugin header files +from VMD that match the binary plugins. These header files in the +directory: /plugins/include For convenience, the package +ships with a set of header files that are compatible with VMD 1.9 and +1.9.1 (the current version in June 2012) + +The person who created this package is Axel Kohlmeyer at Temple U +(akohlmey at gmail.com). Contact him directly if you have questions. diff --git a/src/USER-MOLFILE/dump_molfile.cpp b/src/USER-MOLFILE/dump_molfile.cpp new file mode 100644 index 0000000000..6a32ac8b1f --- /dev/null +++ b/src/USER-MOLFILE/dump_molfile.cpp @@ -0,0 +1,461 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Axel Kohlmeyer (Temple U) +------------------------------------------------------------------------- */ + +#include +#include +#include +#include "dump_molfile.h" +#include "domain.h" +#include "atom.h" +#include "comm.h" +#include "update.h" +#include "output.h" +#include "group.h" +#include "memory.h" +#include "error.h" + +#include "molfile_interface.h" + +using namespace LAMMPS_NS; +typedef MolfileInterface MFI; + +// syntax: +// dump molfile [] +// path defaults to "." -> will look for .so files in CWD. +// +// XXX: potential change: add more options and make them optional +// path +// template (import name and topology information from file) +// bonds (write out bond information) +// topology (write out all topology information) + +/* ---------------------------------------------------------------------- */ + +DumpMolfile::DumpMolfile(LAMMPS *lmp, int narg, char **arg) + : Dump(lmp, narg, arg) +{ + if (narg < 6) error->all(FLERR,"Illegal dump molfile command"); + + if (binary || compressed || multiproc) + error->all(FLERR,"Invalid dump molfile filename"); + + // required settings + + sort_flag = 1; + sortcol = 0; + + // storage for collected information + + size_one = 4; + if (atom->molecule_flag) ++size_one; + if (atom->q_flag) ++size_one; + if (atom->rmass_flag) ++size_one; + if (atom->radius_flag) ++size_one; + + need_structure = 0; + unwrap_flag = 0; + velocity_flag = 0; + topology_flag = 0; + ntotal = 0; + me = comm->me; + + coords = vels = masses = charges = radiuses = NULL; + types = molids = NULL; + ntypes = atom->ntypes; + typenames = NULL; + + // allocate global array for atom coords + + bigint n = group->count(igroup); + if (n > MAXSMALLINT/sizeof(float)) + error->all(FLERR,"Too many atoms for dump molfile"); + if (n < 1) + error->all(FLERR,"Not enough atoms for dump molfile"); + natoms = static_cast(n); + + if (me == 0) { + memory->create(types,natoms,"dump:types"); + memory->create(coords,3*natoms,"dump:coords"); + if (atom->molecule_flag) memory->create(molids,natoms,"dump:molids"); + if (atom->q_flag) memory->create(charges,natoms,"dump:charges"); + if (atom->rmass_flag) memory->create(masses,natoms,"dump:masses"); + if (atom->radius_flag) memory->create(radiuses,natoms,"dump:radiuses"); + + mf = new MolfileInterface(arg[5],MFI::M_WRITE); + + const char *path = (const char *) "."; + if (narg > 6) + path=arg[6]; + + if (mf->find_plugin(path)!= MFI::E_MATCH) + error->one(FLERR,"No suitable molfile plugin found"); + + if (screen) + fprintf(screen,"Dump '%s' uses molfile plugin: %s\n", + id, mf->get_plugin_name()); + if (logfile) + fprintf(logfile,"Dump '%s' uses molfile plugin: %s\n", + id,mf->get_plugin_name()); + } +} + +/* ---------------------------------------------------------------------- */ + +DumpMolfile::~DumpMolfile() +{ + if (me == 0) { + mf->close(); + memory->destroy(types); + memory->destroy(coords); + memory->destroy(vels); + memory->destroy(masses); + memory->destroy(charges); + memory->destroy(radiuses); + delete mf; + } + + if (typenames) { + for (int i = 1; i <= ntypes; i++) + delete [] typenames[i]; + + delete [] typenames; + typenames = NULL; + } +} + +/* ---------------------------------------------------------------------- */ + +void DumpMolfile::init_style() +{ + if (sort_flag == 0 || sortcol != 0) + error->all(FLERR,"Dump molfile requires sorting by atom ID"); + + if (me == 0) { + + /* initialize typenames array to numeric types by default */ + if (typenames == NULL) { + typenames = new char*[ntypes+1]; + for (int itype = 1; itype <= ntypes; itype++) { + /* a 32-bit int can be maximally 10 digits plus sign */ + typenames[itype] = new char[12]; + sprintf(typenames[itype],"%d",itype); + } + } + + // open single file, one time only + if (multifile == 0) openfile(); + } +} + +/* ---------------------------------------------------------------------- */ + +void DumpMolfile::write() +{ + // simulation box dimensions + + if (domain->triclinic == 1) { + double *h = domain->h; + double alen = h[0]; + double blen = sqrt(h[5]*h[5] + h[1]*h[1]); + double clen = sqrt(h[4]*h[4] + h[3]*h[3] + h[2]*h[2]); + cell[0] = alen; + cell[1] = blen; + cell[2] = clen; + cell[3] = (90.0 - asin((h[5]*h[4] + h[1]*h[3]) / blen/clen)); // alpha + cell[4] = (90.0 - asin((h[0]*h[4]) / alen/clen)); // beta + cell[5] = (90.0 - asin((h[0]*h[5]) / alen/blen)); // gamma + } else { + cell[0] = domain->xprd; + cell[1] = domain->yprd; + cell[2] = domain->zprd; + cell[3] = cell[4] = cell[5] = 90.0f; + } + + // nme = # of dump lines this proc will contribute to dump + + nme = count(); + bigint bnme = nme; + + // ntotal = total # of dump lines + // nmax = max # of dump lines on any proc + + int nmax; + MPI_Allreduce(&bnme,&ntotal,1,MPI_LMP_BIGINT,MPI_SUM,world); + MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world); + + // for single file output, the number of atoms must not change. + if (natoms != ntotal) { + if (multifile == 0) { + error->all(FLERR,"Single file molfile dump needs constant #atoms"); + } else { + natoms = ntotal; + } + } + ntotal = 0; + + // if file per timestep, open new file + + if (multifile) openfile(); + + // insure proc 0 can receive everyone's info + // limit nmax*size_one to int since used as arg in MPI_Rsend() below + // pack my data into buf + // if sorting on IDs also request ID list from pack() + // sort buf as needed + + if (nmax > maxbuf) { + if ((bigint) nmax * size_one > MAXSMALLINT) + error->all(FLERR,"Too much per-proc info for dump"); + maxbuf = nmax; + memory->destroy(buf); + memory->create(buf,maxbuf*size_one,"dump:buf"); + } + if (nmax > maxids) { + maxids = nmax; + memory->destroy(ids); + memory->create(ids,maxids,"dump:ids"); + } + + pack(ids); + sort(); + + int tmp,nlines; + MPI_Status status; + MPI_Request request; + + if (me == 0) { + for (int iproc = 0; iproc < nprocs; iproc++) { + if (iproc) { + MPI_Irecv(buf,maxbuf*size_one,MPI_DOUBLE,iproc,0,world,&request); + MPI_Send(&tmp,0,MPI_INT,iproc,0,world); + MPI_Wait(&request,&status); + MPI_Get_count(&status,MPI_DOUBLE,&nlines); + nlines /= size_one; + } else nlines = nme; + + write_data(nlines,buf); + } + + } else { + MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status); + MPI_Rsend(buf,nme*size_one,MPI_DOUBLE,0,0,world); + } +} + +/* ---------------------------------------------------------------------- */ + +void DumpMolfile::openfile() +{ + // single file, already opened, so just return + + if (singlefile_opened) return; + if (multifile == 0) singlefile_opened = 1; + need_structure = 1; + + if (me == 0) { + + // close open file, if needed. + if (mf->is_open()) mf->close(); + + // if one file per timestep, replace '*' with current timestep + + char *filecurrent = new char[strlen(filename) + 16]; + if (multifile == 0) { + strcpy(filecurrent,filename); + } else { + char *ptr = strchr(filename,'*'); + char *p1 = filename; + char *p2 = filecurrent; + while (p1 != ptr) + *p2++ = *p1++; + + if (padflag == 0) { + sprintf(p2,BIGINT_FORMAT "%s",update->ntimestep,ptr+1); + } else { + char bif[8],pad[16]; + strcpy(bif,BIGINT_FORMAT); + sprintf(pad,"%%0%d%s%%s",padflag,&bif[1]); + sprintf(p2,pad,update->ntimestep,ptr+1); + } + } + + if (mf->open(filecurrent,&natoms)) + error->one(FLERR,"Cannot open dump file"); + delete[] filecurrent; + } +} + +/* ---------------------------------------------------------------------- */ + +void DumpMolfile::pack(int *ids) +{ + int m,n; + + int *tag = atom->tag; + int *type = atom->type; + double **x = atom->x; + int *image = atom->image; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + m = n = 0; + if (unwrap_flag) { + double xprd = domain->xprd; + double yprd = domain->yprd; + double zprd = domain->zprd; + double xy = domain->xy; + double xz = domain->xz; + double yz = domain->yz; + + for (int i = 0; i < nlocal; i++) { + if (mask[i] & groupbit) { + int ix = (image[i] & 1023) - 512; + int iy = (image[i] >> 10 & 1023) - 512; + int iz = (image[i] >> 20) - 512; + + buf[m++] = type[i]; + if (domain->triclinic) { + buf[m++] = x[i][0] + ix * xprd + iy * xy + iz * xz; + buf[m++] = x[i][1] + iy * yprd + iz * yz; + buf[m++] = x[i][2] + iz * zprd; + } else { + buf[m++] = x[i][0] + ix * xprd; + buf[m++] = x[i][1] + iy * yprd; + buf[m++] = x[i][2] + iz * zprd; + } + if (atom->molecule_flag) buf[m++] = atom->molecule[i]; + if (atom->q_flag) buf[m++] = atom->q[i]; + if (atom->rmass_flag) buf[m++] = atom->mass[i]; + if (atom->radius_flag) buf[m++] = atom->radius[i]; + ids[n++] = tag[i]; + } + } + + } else { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + buf[m++] = type[i]; + buf[m++] = x[i][0]; + buf[m++] = x[i][1]; + buf[m++] = x[i][2]; + if (atom->molecule_flag) buf[m++] = atom->molecule[i]; + if (atom->q_flag) buf[m++] = atom->q[i]; + if (atom->rmass_flag) buf[m++] = atom->mass[i]; + if (atom->radius_flag) buf[m++] = atom->radius[i]; + ids[n++] = tag[i]; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void DumpMolfile::write_data(int n, double *mybuf) +{ + if (me == 0) { + // copy buf atom coords into global arrays + int m = 0; + for (int i = 0; i < n; i++) { + types[ntotal] = static_cast(mybuf[m++]); + coords[3*ntotal + 0] = mybuf[m++]; + coords[3*ntotal + 1] = mybuf[m++]; + coords[3*ntotal + 2] = mybuf[m++]; + if (atom->molecule_flag) molids[ntotal] = static_cast(mybuf[m++]); + if (atom->q_flag) charges[ntotal] = mybuf[m++]; + if (atom->rmass_flag) masses[ntotal] = mybuf[m++]; + if (atom->radius_flag) radiuses[ntotal] = mybuf[m++]; + ++ntotal; + } + + // if last chunk of atoms in this snapshot, write global arrays to file + + if (ntotal == natoms) { + ntotal = 0; + + if (need_structure) { + mf->property(MFI::P_NAME,types,typenames); + + if (atom->molecule_flag) + mf->property(MFI::P_RESI,molids); + + if (atom->rmass_flag) { + mf->property(MFI::P_MASS,masses); + } else { + mf->property(MFI::P_MASS,types,atom->mass); + } + + if (atom->q_flag) + mf->property(MFI::P_CHRG,charges); + + if (atom->radius_flag) + mf->property(MFI::P_RADS,radiuses); + + // update/write structure information in plugin + mf->structure(); + need_structure = 0; + } + double simtime = update->ntimestep * update->dt; + mf->timestep(coords,NULL,cell,&simtime); + } + } +} + +/* ---------------------------------------------------------------------- */ + +int DumpMolfile::modify_param(int narg, char **arg) +{ + if (strcmp(arg[0],"unwrap") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + if (strcmp(arg[1],"yes") == 0) unwrap_flag = 1; + else if (strcmp(arg[1],"no") == 0) unwrap_flag = 0; + else error->all(FLERR,"Illegal dump_modify command"); + return 2; + + } else if (strcmp(arg[0],"element") == 0) { + if (narg < ntypes+1) + error->all(FLERR, "Dump modify element names do not match atom types"); + + if (typenames) { + for (int i = 1; i <= ntypes; i++) + delete [] typenames[i]; + + delete [] typenames; + typenames = NULL; + } + + typenames = new char*[ntypes+1]; + for (int itype = 1; itype <= ntypes; itype++) { + int n = strlen(arg[itype]) + 1; + typenames[itype] = new char[n]; + strcpy(typenames[itype],arg[itype]); + } + + return ntypes+1; + } + return 0; +} + +/* ---------------------------------------------------------------------- + return # of bytes of allocated memory in buf and global coords array +------------------------------------------------------------------------- */ + +bigint DumpMolfile::memory_usage() +{ + bigint bytes = Dump::memory_usage(); + bytes += memory->usage(coords,natoms*3); + bytes += sizeof(MFI); + return bytes; +} diff --git a/src/USER-MOLFILE/dump_molfile.h b/src/USER-MOLFILE/dump_molfile.h new file mode 100644 index 0000000000..f95bf2eb36 --- /dev/null +++ b/src/USER-MOLFILE/dump_molfile.h @@ -0,0 +1,105 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifdef DUMP_CLASS + +DumpStyle(molfile,DumpMolfile) + +#else + +#ifndef LMP_DUMP_MOLFILE_H +#define LMP_DUMP_MOLFILE_H + +#include "dump.h" + +namespace LAMMPS_NS { + +class DumpMolfile : public Dump { + public: + DumpMolfile(LAMMPS *, int, char**); + virtual ~DumpMolfile(); + virtual void write(); + + protected: + class MolfileInterface *mf; //< handles low-level I/O + // per-atom data + float *coords, *vels, *masses, *charges, *radiuses; + int *types, *molids; + char **typenames; + + int natoms,me,ntotal,ntypes; + int need_structure; + int unwrap_flag; // 1 if writing unwrapped atom coords, 0 if not + int velocity_flag; // 1 if writing velocities, 0 if not + int topology_flag; // 1 if writing topology data, 0 if not + float cell[6]; // cell parameters: A, B, C, alpha, beta, gamma + + virtual void init_style(); + virtual int modify_param(int, char **); + virtual void write_header(bigint) {}; + virtual void pack(int *); + virtual void write_data(int, double *); + virtual bigint memory_usage(); + virtual void openfile(); +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +E: Invalid dump dcd filename + +Filenames used with the dump dcd style cannot be binary or compressed +or cause multiple files to be written. + +E: Too many atoms for dump dcd + +The system size must fit in a 32-bit integer to use this dump +style. + +E: Dump dcd requires sorting by atom ID + +Use the dump_modify sort command to enable this. + +E: Cannot use variable every setting for dump dcd + +The format of Molfile dump files requires snapshots be output +at a constant frequency. + +E: Cannot change dump_modify every for dump dcd + +The frequency of writing dump dcd snapshots cannot be changed. + +E: Cannot open dump file + +The output file for the dump command cannot be opened. Check that the +path and name are correct. + +E: Dump dcd of non-matching # of atoms + +Every snapshot written by dump dcd must contain the same # of atoms. + +E: Too big a timestep for dump dcd + +The timestep must fit in a 32-bit integer to use this dump style. + +*/ diff --git a/src/USER-MOLFILE/molfile_interface.cpp b/src/USER-MOLFILE/molfile_interface.cpp new file mode 100644 index 0000000000..c0f9789c9e --- /dev/null +++ b/src/USER-MOLFILE/molfile_interface.cpp @@ -0,0 +1,1052 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Axel Kohlmeyer (Temple) +------------------------------------------------------------------------- */ + +#include "molfile_interface.h" + +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#else +#include +#include +#endif + +#include "molfile_plugin.h" + +#if vmdplugin_ABIVERSION < 16 +#error "unsupported VMD molfile plugin ABI version" +#endif + +#define DEBUG 0 + +extern "C" { + typedef int (*initfunc)(void); + typedef int (*regfunc)(void *, vmdplugin_register_cb); + typedef int (*finifunc)(void); + + typedef struct { + void *p; + const char *name; + } plugin_reginfo_t; + + // callback function for plugin registration. + static int plugin_register_cb(void *v, vmdplugin_t *p) + { + plugin_reginfo_t *r = static_cast(v); + // make sure we have the proper plugin type (native reader) + // for the desired file type (called "name" at this level) + if ((strcmp(MOLFILE_PLUGIN_TYPE,p->type) == 0) + && (strcmp(r->name, p->name) == 0) ) { + r->p = static_cast(p); + } + return 0; + } + + /* periodic table of elements for translation of ordinal to atom type */ + static const char *pte_label[] = { + "X", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", + "Na", "Mg", "Al", "Si", "P" , "S", "Cl", "Ar", "K", "Ca", "Sc", + "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", + "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", + "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", + "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", + "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", + "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", + "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", + "Es", "Fm", "Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", + "Ds", "Rg" + }; + static const int nr_pte_entries = sizeof(pte_label) / sizeof(char *); + + /* corresponding table of masses. */ + static const float pte_mass[] = { + /* X */ 0.00000, 1.00794, 4.00260, 6.941, 9.012182, 10.811, + /* C */ 12.0107, 14.0067, 15.9994, 18.9984032, 20.1797, + /* Na */ 22.989770, 24.3050, 26.981538, 28.0855, 30.973761, + /* S */ 32.065, 35.453, 39.948, 39.0983, 40.078, 44.955910, + /* Ti */ 47.867, 50.9415, 51.9961, 54.938049, 55.845, 58.9332, + /* Ni */ 58.6934, 63.546, 65.409, 69.723, 72.64, 74.92160, + /* Se */ 78.96, 79.904, 83.798, 85.4678, 87.62, 88.90585, + /* Zr */ 91.224, 92.90638, 95.94, 98.0, 101.07, 102.90550, + /* Pd */ 106.42, 107.8682, 112.411, 114.818, 118.710, 121.760, + /* Te */ 127.60, 126.90447, 131.293, 132.90545, 137.327, + /* La */ 138.9055, 140.116, 140.90765, 144.24, 145.0, 150.36, + /* Eu */ 151.964, 157.25, 158.92534, 162.500, 164.93032, + /* Er */ 167.259, 168.93421, 173.04, 174.967, 178.49, 180.9479, + /* W */ 183.84, 186.207, 190.23, 192.217, 195.078, 196.96655, + /* Hg */ 200.59, 204.3833, 207.2, 208.98038, 209.0, 210.0, 222.0, + /* Fr */ 223.0, 226.0, 227.0, 232.0381, 231.03588, 238.02891, + /* Np */ 237.0, 244.0, 243.0, 247.0, 247.0, 251.0, 252.0, 257.0, + /* Md */ 258.0, 259.0, 262.0, 261.0, 262.0, 266.0, 264.0, 269.0, + /* Mt */ 268.0, 271.0, 272.0 + }; + + /* + * corresponding table of VDW radii. + * van der Waals radii are taken from A. Bondi, + * J. Phys. Chem., 68, 441 - 452, 1964, + * except the value for H, which is taken from R.S. Rowland & R. Taylor, + * J.Phys.Chem., 100, 7384 - 7391, 1996. Radii that are not available in + * either of these publications have RvdW = 2.00 Å. + * The radii for Ions (Na, K, Cl, Ca, Mg, and Cs are based on the CHARMM27 + * Rmin/2 parameters for (SOD, POT, CLA, CAL, MG, CES) by default. + */ + static const float pte_vdw_radius[] = { + /* X */ 1.5, 1.2, 1.4, 1.82, 2.0, 2.0, + /* C */ 1.7, 1.55, 1.52, 1.47, 1.54, + /* Na */ 1.36, 1.18, 2.0, 2.1, 1.8, + /* S */ 1.8, 2.27, 1.88, 1.76, 1.37, 2.0, + /* Ti */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Ni */ 1.63, 1.4, 1.39, 1.07, 2.0, 1.85, + /* Se */ 1.9, 1.85, 2.02, 2.0, 2.0, 2.0, + /* Zr */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Pd */ 1.63, 1.72, 1.58, 1.93, 2.17, 2.0, + /* Te */ 2.06, 1.98, 2.16, 2.1, 2.0, + /* La */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Eu */ 2.0, 2.0, 2.0, 2.0, 2.0, + /* Er */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* W */ 2.0, 2.0, 2.0, 2.0, 1.72, 1.66, + /* Hg */ 1.55, 1.96, 2.02, 2.0, 2.0, 2.0, 2.0, + /* Fr */ 2.0, 2.0, 2.0, 2.0, 2.0, 1.86, + /* Np */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Md */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + /* Mt */ 2.0, 2.0, 2.0 + }; + + /* lookup functions */ + + static const char *get_pte_label(const int idx) + { + if ((idx < 1) || (idx >= nr_pte_entries)) return pte_label[0]; + + return pte_label[idx]; + } + + static float get_pte_mass(const int idx) + { + if ((idx < 1) || (idx >= nr_pte_entries)) return pte_mass[0]; + + return pte_mass[idx]; + } + + static float get_pte_vdw_radius(const int idx) + { + if ((idx < 1) || (idx >= nr_pte_entries)) return pte_vdw_radius[0]; + +#if 1 + /* Replace with Hydrogen radius with an "all-atom" radius */ + if (idx == 1) + return 1.0; /* H */ +#else + /* Replace with old VMD atom radii values */ + switch (idx) { + case 1: return 1.0; /* H */ + case 6: return 1.5; /* C */ + case 7: return 1.4; /* N */ + case 8: return 1.3; /* O */ + case 9: return 1.2; /* F */ + case 15: return 1.5; /* P */ + case 16: return 1.9; /* S */ + } +#endif + + return pte_vdw_radius[idx]; + } + + static int get_pte_idx(const char *label) + { + int i; + char atom[3]; + + /* zap string */ + atom[0] = (char) 0; + atom[1] = (char) 0; + atom[2] = (char) 0; + /* if we don't have a null-pointer, there must be at least two + * chars, which is all we need. we convert to the capitalization + * convention of the table above during assignment. */ + if (label != NULL) { + atom[0] = (char) toupper((int) label[0]); + atom[1] = (char) tolower((int) label[1]); + } + /* discard numbers in atom label */ + if (isdigit(atom[1])) atom[1] = (char) 0; + + for (i=0; i < nr_pte_entries; ++i) { + if ( (pte_label[i][0] == atom[0]) + && (pte_label[i][1] == atom[1]) ) return i; + } + + return 0; + } + + static int get_pte_idx_from_string(const char *label) { + int i, ind; + char atom[3]; + + if (label != NULL) { + /* zap string */ + atom[0] = atom[1] = atom[2] = '\0'; + + for (ind=0,i=0; (ind<2) && (label[i]!='\0'); i++) { + if (label[i] != ' ') { + atom[ind] = toupper(label[i]); + ind++; + } + } + + if (ind < 1) + return 0; /* no non-whitespace characters */ + + for (i=0; i < nr_pte_entries; ++i) { + if ((toupper(pte_label[i][0]) == atom[0]) && (toupper(pte_label[i][1]) == atom[1])) + return i; + } + } + + return 0; + } + + // directory traversal helper functions + +#if defined(_WIN32) + + // Win32 directory traversal handle + typedef struct { + HANDLE h; + WIN32_FIND_DATA fd; + char *name; + char *searchname; + int dlen; + } dirhandle_t; + + // open a directory handle + static dirhandle_t *my_opendir(const char *dirname) + { + dirhandle_t *d; + int len; + + if (dirname == NULL) + return NULL; + d = new dirhandle_t; + + len = 2 + strlen(dirname); + d->name = new char[len]; + strcpy(d->name, dirname); + strcat(d->name, "\\"); + d->dlen = len; + + len += 1; + d->searchname = new char[len]; + strcpy(d->searchname, dirname); + strcat(d->searchname, "\\*"); + + d->h = FindFirstFile(d->searchname, &(d->fd)); + if (d->h == ((HANDLE)(-1))) { + delete[] d->searchname; + delete[] d->name; + delete d; + return NULL; + } + return d; + } + + // get next file name from directory handle + static char *my_readdir(dirhandle_t *d) + { + if (FindNextFile(d->h, &(d->fd))) { + return d->fd.cFileName; + } + return NULL; + } + + // close directory handle + static void my_closedir(dirhandle_t *d) + { + if (d->h != NULL) { + FindClose(d->h); + } + delete[] d->searchname; + delete[] d->name; + delete d; + } + + // open a shared object file + static void *my_dlopen(const char *fname) { + return (void *)LoadLibrary(fname); + } + + // report error message from dlopen + static const char *my_dlerror(void) { + static CHAR szBuf[80]; + DWORD dw = GetLastError(); + + sprintf(szBuf, "my_dlopen failed: GetLastError returned %u\n", dw); + return szBuf; + } + + // resolve a symbol in shared object + static void *my_dlsym(void *h, const char *sym) { + return (void *)GetProcAddress((HINSTANCE)h, sym); + } + + // close a shared object + static int my_dlclose(void *h) { + /* FreeLibrary returns nonzero on success */ + return !FreeLibrary((HINSTANCE)h); + } + +#else + + // Unix directory traversal handle + typedef struct { + DIR *d; + char *name; + int dlen; + } dirhandle_t; + + // open a directory handle + static dirhandle_t *my_opendir(const char *dirname) + { + dirhandle_t *d; + int len; + + if (dirname == NULL) return NULL; + + d = new dirhandle_t; + len = 2 + strlen(dirname); + d->name = new char[len]; + strcpy(d->name,dirname); + strcat(d->name,"/"); + d->dlen = len; + + d->d = opendir(d->name); + if (d->d == NULL) { + delete[] d->name; + delete d; + return NULL; + } + return d; + } + + // get next file name from directory handle + static char *my_readdir(dirhandle_t *d) + { + struct dirent *p; + + if ((p = readdir(d->d)) != NULL) { + return p->d_name; + } + + return NULL; + } + + // close directory handle + static void my_closedir(dirhandle_t *d) + { + if (d->d != NULL) { + closedir(d->d); + } + delete[] d->name; + delete d; + return; + } + + // open a shared object file + static void *my_dlopen(const char *fname) { + return dlopen(fname, RTLD_NOW); + } + + // report error message from dlopen + static const char *my_dlerror(void) { + return dlerror(); + } + + // resolve a symbol in shared object + static void *my_dlsym(void *h, const char *sym) { + return dlsym(h, sym); + } + + // close a shared object + static int my_dlclose(void *h) { + return dlclose(h); + } + +#endif + +} // end of extern "C" region + +using namespace LAMMPS_NS; + +// constructor. +MolfileInterface::MolfileInterface(const char *type, const int mode) + : _plugin(0), _dso(0), _ptr(0), _info(0), _natoms(0), + _mode(mode), _caps(M_NONE) +{ + _name = new char[5]; + strcpy(_name,"none"); + _type = new char[1+strlen(type)]; + strcpy(_type,type); +} + +// destructor. +MolfileInterface::~MolfileInterface() +{ + forget_plugin(); + + if (_info) { + molfile_atom_t *a = static_cast(_info); + delete[] a; + _info = NULL; + } + delete[] _name; + delete[] _type; +} + +// register the best matching plugin in a given directory +int MolfileInterface::find_plugin(const char *pluginpath) +{ + dirhandle_t *dir; + char *filename, *ext, *next, *path, *plugindir; + int retval = E_NONE; + +#if defined(_WIN32) +#define MY_PATHSEP ';' +#else +#define MY_PATHSEP ':' +#endif + if (pluginpath == NULL) return E_DIR; + plugindir = path = strdup(pluginpath); + + while (plugindir) { + // check if this a single directory or path. + next = strchr(plugindir,MY_PATHSEP); + if (next) { + *next = NULL; + ++next; + } + + dir = my_opendir(plugindir); + if (!dir) + retval = (retval > E_DIR) ? retval : E_DIR; + + // search for suitable file names and try to inspect them + while(dir) { + char *fullname; + int len; + + filename = my_readdir(dir); + if (filename == NULL) break; + + // only look at .so files + ext = strrchr(filename, '.'); + if (ext == NULL) continue; + if (strcasecmp(ext,".so") != 0) continue; + + // construct full pathname of potential DSO + len = dir->dlen; + len += strlen(filename); + fullname = new char[len]; + strcpy(fullname,dir->name); + strcat(fullname,filename); + + // try to register plugin at file name. + int rv = load_plugin(fullname); + if (rv > retval) retval = rv; + + delete[] fullname; + } + if (dir) + my_closedir(dir); + + plugindir = next; + } + free(path); + return retval; +} + +// register the best matching plugin in a given directory +int MolfileInterface::load_plugin(const char *filename) +{ + void *dso; + int len, retval = E_NONE; + + // access shared object + dso = my_dlopen(filename); + if (dso == NULL) + return E_FILE; + + // check for required plugin symbols + void *ifunc = my_dlsym(dso,"vmdplugin_init"); + void *rfunc = my_dlsym(dso,"vmdplugin_register"); + void *ffunc = my_dlsym(dso,"vmdplugin_fini"); + if (ifunc == NULL || rfunc == NULL || ffunc == NULL) { + my_dlclose(dso); + return E_SYMBOL; + } + + // intialize plugin. skip plugin if it fails. + if (((initfunc)(ifunc))()) { + my_dlclose(dso); + return E_SYMBOL; + } + + // pre-register plugin. + // the callback will be called for each plugin in the DSO and + // check the file type. plugin->name will change if successful. + plugin_reginfo_t reginfo; + reginfo.p = NULL; + reginfo.name=_type; + ((regfunc)rfunc)(®info, plugin_register_cb); + + // make some checks to see if the plugin is suitable or not. + molfile_plugin_t *plugin = static_cast(reginfo.p); + + // if the callback found a matching plugin and copied the struct, + // its name element will point to a different location now. + if (plugin == NULL) { + retval = E_TYPE; + + // check if the ABI matches the one used to compile this code + } else if (plugin->abiversion != vmdplugin_ABIVERSION) { + retval = E_ABI; + + // check if (basic) reading is supported + } else if ((_mode & M_READ) && + ( (plugin->open_file_read == NULL) || + (plugin->read_next_timestep == NULL) || + (plugin->close_file_read == NULL) )) { + retval = E_MODE; + + // check if (basic) writing is supported + } else if ( (_mode & M_WRITE) && + ( (plugin->open_file_write == NULL) || + (plugin->write_timestep == NULL) || + (plugin->close_file_write == NULL) )) { + retval = E_MODE; + + // make some additional check, if we + // already have a plugin registered. + // NOTE: this has to come last. + } else if (_dso && _plugin) { + molfile_plugin_t *p; + p = static_cast(_plugin); + + // check if the new plugin is of a newer major version + if (p->majorv > plugin->majorv) { + retval = E_VERSION; + + // check if the new plugin is of a newer minor version + } else if ( (p->majorv == plugin->majorv) && + (p->minorv >= plugin->minorv) ) { + retval = E_VERSION; + } + } + + // bingo! this one is a keeper. + if (retval == E_NONE) { + + // make sure any existing plugin is wiped out + forget_plugin(); + + delete[] _name; + len = 16; + len += strlen(plugin->prettyname); + len += strlen(plugin->author); + _name = new char[len]; + sprintf(_name,"%s v%d.%d by %s",plugin->prettyname, + plugin->majorv, plugin->minorv, plugin->author); + + // determine plugin capabilities + _caps = M_NONE; + if (plugin->read_next_timestep) _caps |= M_READ; + if (plugin->write_timestep) _caps |= M_WRITE; + if (plugin->read_structure) _caps |= M_RSTRUCT; + if (plugin->write_structure) _caps |= M_WSTRUCT; + if (plugin->read_bonds) _caps |= M_RBONDS; + if (plugin->write_bonds) _caps |= M_WBONDS; + if (plugin->read_angles) _caps |= M_RANGLES; + if (plugin->write_angles) _caps |= M_WANGLES; + if (plugin->read_volumetric_data) _caps |= M_RVOL; + if (plugin->write_volumetric_data) _caps |= M_WVOL; + + if (_mode & M_WRITE) + _mode |= (_caps & M_WSTRUCT); + else if (_mode & M_READ) + _mode |= (_caps & M_RSTRUCT); + + _plugin = plugin; + _dso = dso; + return E_MATCH; + } + + // better luck next time. clean up and return. + my_dlclose(dso); + return retval; +} + +// deregister a plugin and close or reset all associated objects. +void MolfileInterface::forget_plugin() +{ + if (_ptr) + close(); + + if (_plugin) + _plugin = NULL; + + if (_dso) { + void *ffunc = my_dlsym(_dso,"vmdplugin_fini"); + if (ffunc) + ((finifunc)ffunc)(); + my_dlclose(_dso); + } + _dso = NULL; + + delete[] _name; + _name = new char[5]; + strcpy(_name,"none"); + + _caps = M_NONE; +} + +// open file for writing +int MolfileInterface::open(const char *name, int *natoms) +{ + if (!_plugin || !_dso || !natoms) + return E_FILE; + molfile_plugin_t *p = static_cast(_plugin); + + if (_mode & M_WRITE) + _ptr = p->open_file_write(name,_type,*natoms); + else if (_mode & M_READ) + _ptr = p->open_file_read(name,_type,natoms); + + if (_ptr == NULL) + return E_FILE; + + _natoms = *natoms; + // we need to deal with structure information, + // so we allocate and initialize storage for it. + if (_mode & (M_RSTRUCT|M_WSTRUCT)) { + molfile_atom_t *a = new molfile_atom_t[_natoms]; + _info = a; + memset(_info,0,_natoms*sizeof(molfile_atom_t)); + for (int i=0; i < _natoms; ++i) { + a[i].name[0] = 'X'; + a[i].type[0] = a[i].resname[0] = a[i].segid[0] = 'U'; + a[i].type[1] = a[i].resname[1] = a[i].segid[1] = 'N'; + a[i].type[2] = a[i].resname[2] = a[i].segid[2] = 'K'; + a[i].chain[0] = 'X'; + } + } + return E_NONE; +} + +// get of set atom structure information +int MolfileInterface::structure() +{ + if (!_plugin || !_dso) + return E_FILE; + molfile_plugin_t *p = static_cast(_plugin); + + int optflags = MOLFILE_NOOPTIONS; + + if (_mode & M_WSTRUCT) { + optflags |= (_props & P_BFAC) ? MOLFILE_BFACTOR : 0; + optflags |= (_props & P_OCCP) ? MOLFILE_OCCUPANCY : 0; + optflags |= (_props & P_MASS) ? MOLFILE_MASS : 0; + optflags |= (_props & P_CHRG) ? MOLFILE_CHARGE : 0; + optflags |= (_props & P_RADS) ? MOLFILE_RADIUS : 0; + optflags |= (_props & P_ATMN) ? MOLFILE_ATOMICNUMBER : 0; + + molfile_atom_t *a = static_cast(_info); + p->write_structure(_ptr,optflags,a); + } else if (_mode & M_READ) { + ; // XXX: FIXME + } + return 0; +} + +// safely close file +int MolfileInterface::close() +{ + if (!_plugin || !_dso || !_ptr) + return E_FILE; + + molfile_plugin_t *p = static_cast(_plugin); + + if (_mode & M_WRITE) { + p->close_file_write(_ptr); + } else if (_mode & M_READ) { + p->close_file_read(_ptr); + } + + if (_info) { + molfile_atom_t *a = static_cast(_info); + delete[] a; + _info = NULL; + } + _ptr = NULL; + _natoms = 0; + + return E_NONE; +} + + +// read or write timestep +int MolfileInterface::timestep(float *coords, float *vels, + float *cell, double *simtime) +{ + if (!_plugin || !_dso || !_ptr) + return 1; + + molfile_plugin_t *p = static_cast(_plugin); + molfile_timestep_t *t = new molfile_timestep_t; + int rv; + + if (_mode & M_WRITE) { + t->coords = coords; + t->velocities = vels; + if (cell != NULL) { + t->A = cell[0]; + t->B = cell[1]; + t->C = cell[2]; + t->alpha = cell[3]; + t->beta = cell[4]; + t->gamma = cell[5]; + } else { + t->A = 0.0; + t->B = 0.0; + t->C = 0.0; + t->alpha = 90.0; + t->beta = 90.0; + t->gamma = 90.0; + } + + if (simtime) + t->physical_time = *simtime; + else + t->physical_time = 0.0; + + rv = p->write_timestep(_ptr,t); + + } else { + t->coords = coords; + t->velocities = vels; + rv = p->read_next_timestep(_ptr, _natoms, t); + if (cell != NULL) { + cell[0] = t->A; + cell[1] = t->B; + cell[2] = t->C; + cell[3] = t->alpha; + cell[4] = t->beta; + cell[5] = t->gamma; + } + + if (simtime) + *simtime = t->physical_time; + } + + return 0; +} + +#define PROPUPDATE(PROP,ENTRY,VAL) \ + if ((propid & PROP) == PROP) { a.ENTRY = VAL; plist |= PROP; } + +#define PROPSTRCPY(PROP,ENTRY,VAL) \ + if ((propid & PROP) == PROP) { strcpy(a.ENTRY,VAL); plist |= PROP; } + +// floating point props +static int write_atom_property(molfile_atom_t &a, + const int propid, + const float prop) +{ + int plist = MolfileInterface::P_NONE; + PROPUPDATE(MolfileInterface::P_OCCP,occupancy,prop); + PROPUPDATE(MolfileInterface::P_BFAC,bfactor,prop); + PROPUPDATE(MolfileInterface::P_MASS,mass,prop); + PROPUPDATE(MolfileInterface::P_CHRG,charge,prop); + PROPUPDATE(MolfileInterface::P_RADS,radius,prop); + return plist; +} + +// double precision floating point props +static int write_atom_property(molfile_atom_t &a, + const int propid, + const double prop) +{ + return write_atom_property(a,propid,static_cast(prop)); +} + +// integer and derived props +static int write_atom_property(molfile_atom_t &a, + const int propid, + const int prop) +{ + int plist = MolfileInterface::P_NONE; + PROPUPDATE(MolfileInterface::P_RESI,resid,prop); + PROPUPDATE(MolfileInterface::P_ATMN,atomicnumber,prop); + PROPUPDATE((MolfileInterface::P_ATMN|MolfileInterface::P_MASS), + mass,get_pte_mass(prop)); + PROPSTRCPY((MolfileInterface::P_ATMN|MolfileInterface::P_NAME), + name,get_pte_label(prop)); + PROPSTRCPY((MolfileInterface::P_ATMN|MolfileInterface::P_TYPE), + type,get_pte_label(prop)); + return plist; +} + +// integer and derived props +static int write_atom_property(molfile_atom_t &a, + const int propid, + const char *prop) +{ + int plist = MolfileInterface::P_NONE; + PROPSTRCPY(MolfileInterface::P_NAME,name,prop); + PROPSTRCPY(MolfileInterface::P_TYPE,type,prop); + PROPSTRCPY(MolfileInterface::P_RESN,resname,prop); + PROPSTRCPY(MolfileInterface::P_SEGN,segid,prop); + return plist; +} +#undef PROPUPDATE +#undef PROPSTRCPY + +// set/get atom floating point property +int MolfileInterface::property(int propid, int idx, float *prop) +{ + if ((_info == NULL) || (prop == NULL) || (idx < 0) || (idx >= _natoms)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) + return write_atom_property(a[idx], propid, *prop); + + return _props; +} + +// set/get per type floating point property +int MolfileInterface::property(int propid, int *types, float *prop) +{ + if ((_info == NULL) || (types == NULL) || (prop == NULL)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + for (int i=0; i < _natoms; ++i) + _props |= write_atom_property(a[i], propid, prop[types[i]]); + } + return _props; +} + +// set/get per atom floating point property +int MolfileInterface::property(int propid, float *prop) +{ + if ((_info == NULL) || (prop == NULL)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + for (int i=0; i < _natoms; ++i) + _props |= write_atom_property(a[i], propid, prop[i]); + } + return _props; +} + +// set/get atom floating point property +int MolfileInterface::property(int propid, int idx, double *prop) +{ + if ((_info == NULL) || (prop == NULL) || (idx < 0) || (idx >= _natoms)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) + return write_atom_property(a[idx], propid, *prop); + + return _props; +} + +// set/get per type floating point property +int MolfileInterface::property(int propid, int *types, double *prop) +{ + if ((_info == NULL) || (types == NULL) || (prop == NULL)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + for (int i=0; i < _natoms; ++i) + _props |= write_atom_property(a[i], propid, prop[types[i]]); + } + return _props; +} + +// set/get per atom floating point property +int MolfileInterface::property(int propid, double *prop) +{ + if ((_info == NULL) || (prop == NULL)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + for (int i=0; i < _natoms; ++i) + _props |= write_atom_property(a[i], propid, prop[i]); + } + return _props; +} + +#define INT_TO_STRING_BODY(IDX) \ + buf[15] = 0; \ + if (propid & P_NAME) \ + _props |= write_atom_property(a[IDX],P_NAME,buf); \ + if (propid & P_TYPE) \ + _props |= write_atom_property(a[IDX],P_TYPE,buf); \ + buf[7] = 0; \ + if (propid & P_RESN) \ + _props |= write_atom_property(a[IDX],P_RESN,buf); \ + if (propid & P_SEGN) \ + _props |= write_atom_property(a[IDX],P_SEGN,buf); \ + buf[1] = 0; \ + if (propid & P_CHAI) \ + _props |= write_atom_property(a[IDX],P_CHAI,buf) + +// set/get atom integer property +int MolfileInterface::property(int propid, int idx, int *prop) +{ + if ((_info == NULL) || (prop == NULL) || (idx < 0) || (idx >= _natoms)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + char buf[64]; + + _props |= write_atom_property(a[idx], propid, *prop); + + if (propid & (P_NAME|P_TYPE|P_RESN|P_SEGN|P_CHAI)) { + sprintf(buf,"%d",*prop); + INT_TO_STRING_BODY(idx); + } + } + return _props; +} + +// set/get per type integer property +int MolfileInterface::property(int propid, int *types, int *prop) +{ + if ((_info == NULL) || (types == NULL) || (prop == NULL)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + char buf[64]; + + for (int i=0; i < _natoms; ++i) + _props |= write_atom_property(a[i], propid, prop[types[i]]); + + if (propid & (P_NAME|P_TYPE|P_RESN|P_SEGN|P_CHAI)) { + for (int i=0; i < _natoms; ++i) { + sprintf(buf,"%d",prop[types[i]]); + INT_TO_STRING_BODY(i); + } + } + } + return _props; +} + +// set/get per atom integer property +int MolfileInterface::property(int propid, int *prop) +{ + if ((_info == NULL) || (prop == NULL)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + char buf[64]; + + for (int i=0; i < _natoms; ++i) + _props |= write_atom_property(a[i],propid,prop[i]); + + if (propid & (P_NAME|P_TYPE|P_RESN|P_SEGN|P_CHAI)) { + for (int i=0; i < _natoms; ++i) { + sprintf(buf,"%d",prop[i]); + INT_TO_STRING_BODY(i); + } + } + } + return _props; +} +#undef INT_TO_STRING_BODY + +// set/get atom string property +int MolfileInterface::property(int propid, int idx, char *prop) +{ + if ((_info == NULL) || (prop == NULL) || (idx < 0) || (idx >= _natoms)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + _props |= write_atom_property(a[idx], propid, prop); + } + return _props; +} + +// set/get per type string property +int MolfileInterface::property(int propid, int *types, char **prop) +{ + if ((_info == NULL) || (types == NULL) || (prop == NULL)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + for (int i=0; i < _natoms; ++i) { + _props |= write_atom_property(a[i], propid, prop[types[i]]); + } + } + return _props; +} + +// set/get per atom string property +int MolfileInterface::property(int propid, char **prop) +{ + if ((_info == NULL) || (prop == NULL)) + return P_NONE; + + molfile_atom_t *a = static_cast(_info); + + if (_mode & M_WSTRUCT) { + for (int i=0; i < _natoms; ++i) { + _props |= write_atom_property(a[i], propid, prop[i]); + } + } + return _props; +} + + diff --git a/src/USER-MOLFILE/molfile_interface.h b/src/USER-MOLFILE/molfile_interface.h new file mode 100644 index 0000000000..0dbf051c06 --- /dev/null +++ b/src/USER-MOLFILE/molfile_interface.h @@ -0,0 +1,158 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Axel Kohlmeyer (Temple) +------------------------------------------------------------------------- */ + +#ifndef LMP_MOLFILE_INTERFACE_H +#define LMP_MOLFILE_INTERFACE_H + +namespace LAMMPS_NS { + +// This class provides an abstract interface +// to the VMD plugin library. + +class MolfileInterface +{ + public: + // plugin modes. + enum {M_NONE=0, + M_READ = 1<<0, M_WRITE = 1<<1, + M_RSTRUCT = 1<<2, M_WSTRUCT = 1<<3, + M_RBONDS = 1<<4, M_WBONDS = 1<<5, + M_RANGLES = 1<<6, M_WANGLES = 1<<7, + M_RVOL = 1<<8, M_WVOL = 1<<9, + M_LAST }; + + // plugin finder return values. + enum {E_NONE=0, //< nothing happened + E_DIR, //< path is not a directory or not readable + E_FILE, //< file not a DSO or not readable + E_SYMBOL, //< DSO is not a VMD plugin + E_TYPE, //< plugin is not of the correct type + E_ABI, //< plugin ABI does not match + E_MODE, //< plugin does not support desired mode + E_VERSION, //< plugin is not newer as the current one + E_MATCH, //< plugin matches + E_LAST //< last entry + }; + + // atom structure properties. deliberately not complete. + enum {P_NONE=0, //< no structure information available + P_NAME=1<<0, //< atom name, char[16] + P_TYPE=1<<1, //< atom type, char[16] + P_RESN=1<<2, //< residue name, char[ 8] + P_RESI=1<<3, //< residue index, int + P_SEGN=1<<4, //< segment name, char[ 8] + P_CHAI=1<<5, //< chain id, char[ 2] + P_OCCP=1<<6, //< occupancy, float + P_BFAC=1<<7, //< B factor, float + P_MASS=1<<8, //< atom mass, float + P_CHRG=1<<9, //< atom charge, float + P_RADS=1<<10, //< atom radius, float + P_ATMN=1<<11, //< atomic number, int + P_LAST //< last entry + }; + + MolfileInterface(const char *type, const int mode); + ~MolfileInterface(); + + // disallowed default methods + private: + MolfileInterface() {}; + MolfileInterface(const MolfileInterface &) {}; + MolfileInterface &operator =(const MolfileInterface &) {return *this;}; + + public: + // search in the given directory path for a molfile plugin that + // is of the right type and supports the desired mode. + // if a plugin is already registered and a newer version is + // found, this new version will override the old one. + int find_plugin(const char *path); + // try to register the plugin at given file name + int load_plugin(const char *name); + // deregister the current plugin/DSO and clean up. + void forget_plugin(); + // return formatted string describing plugin + char *get_plugin_name() const { return _name; }; + // return canonical plugin name (= file type) + char *get_plugin_type() const { return _type; }; + + // file operations + + // open file through plugin + int open(const char *name, int *natoms); + // read/write structure info + int structure(); + // read/write timestep + int timestep(float *coords, float *vels, float *cell, double *simtime); + // close file managed by plugin + int close(); + + // inquire on interface status + + // true if file stream is active. + bool is_open() const { return (_ptr != 0); }; + // true if file format requires or provides atom properties + bool has_props() const { return (_mode & (M_RSTRUCT|M_WSTRUCT)) != 0; }; + + // return number of atoms in current file. -1 if closed/invalid; + bool get_natoms() const { return _natoms; }; + // return property bitmask + bool get_props() const { return _props; }; + + // atom property operations + + // set/get atom floating point property + int property(int propid, int idx, float *prop); + // set/get per type floating point property + int property(int propid, int *types, float *prop); + // set/get per atom floating point property + int property(int propid, float *prop); + // set/get atom floating point property + int property(int propid, int idx, double *prop); + // set/get per type floating point property + int property(int propid, int *types, double *prop); + // set/get per atom floating point property + int property(int propid, double *prop); + // set/get atom integer property + int property(int propid, int idx, int *prop); + // set/get per type integer property + int property(int propid, int *types, int *prop); + // set/get per atom integer property + int property(int propid, int *prop); + // set/get atom string property + int property(int propid, int idx, char *prop); + // set/get per type string property + int property(int propid, int *types, char **prop); + // set/get per atom string property + int property(int propid, char **prop); + + // internal data + protected: + void *_plugin; // pointer to plugin struct + void *_dso; // handle to DSO + void *_ptr; // pointer to plugin data handle + void *_info; // pointer to atomic info data + char *_type; // canonical plugin name + char *_name; // plugin formatted name + int _natoms; // number of atoms + int _mode; // plugin mode of operation + int _caps; // plugin capabilities + int _props; // accumulated/available properties +}; + +} + +#endif diff --git a/src/USER-MOLFILE/molfile_plugin.h b/src/USER-MOLFILE/molfile_plugin.h new file mode 100644 index 0000000000..94f6dc36ac --- /dev/null +++ b/src/USER-MOLFILE/molfile_plugin.h @@ -0,0 +1,891 @@ +/*************************************************************************** + *cr + *cr (C) Copyright 1995-2006 The Board of Trustees of the + *cr University of Illinois + *cr All Rights Reserved + *cr + ***************************************************************************/ + +/*************************************************************************** + * RCS INFORMATION: + * + * $RCSfile: molfile_plugin.h,v $ + * $Author: johns $ $Locker: $ $State: Exp $ + * $Revision: 1.103 $ $Date: 2011/03/05 03:56:11 $ + * + ***************************************************************************/ + +/** @file + * API for C extensions to define a way to load structure, coordinate, + * trajectory, and volumetric data files + */ + +#ifndef MOL_FILE_PLUGIN_H +#define MOL_FILE_PLUGIN_H + +#include "vmdplugin.h" + +#if defined(DESRES_READ_TIMESTEP2) +/* includes needed for large integer types used for frame counts */ +#include +typedef ssize_t molfile_ssize_t; /**< for frame counts */ +#endif + +/** + * Define a common plugin type to be used when registering the plugin. + */ +#define MOLFILE_PLUGIN_TYPE "mol file reader" + +/** + * File converter plugins use the same API but register under a different + * type so that regular file readers can have priority. + */ +#define MOLFILE_CONVERTER_PLUGIN_TYPE "mol file converter" + +/* File plugin symbolic constants for better code readability */ +#define MOLFILE_SUCCESS 0 /**< succeeded in reading file */ +#define MOLFILE_EOF -1 /**< end of file */ +#define MOLFILE_ERROR -1 /**< error reading/opening a file */ +#define MOLFILE_NOSTRUCTUREDATA -2 /**< no structure data in this file */ + +#define MOLFILE_NUMATOMS_UNKNOWN -1 /**< unknown number of atoms */ +#define MOLFILE_NUMATOMS_NONE 0 /**< no atoms in this file type */ + +/** + * Maximum string size macro + */ +#define MOLFILE_BUFSIZ 81 /**< maximum chars in string data */ +#define MOLFILE_BIGBUFSIZ 4096 /**< maximum chars in long strings */ + +#define MOLFILE_MAXWAVEPERTS 25 /**< maximum number of wavefunctions + * per timestep */ + + +/** + * File level comments, origin information, and annotations. + */ +typedef struct { + char database[81]; /**< database of origin, if any */ + char accession[81]; /**< database accession code, if any */ + char date[81]; /**< date/time stamp for this data */ + char title[81]; /**< brief title for this data */ + int remarklen; /**< length of remarks string */ + char *remarks; /**< free-form remarks about data */ +} molfile_metadata_t; + + +/* + * Struct for specifying atoms in a molecular structure. The first + * six components are required, the rest are optional and their presence is + * indicating by setting the corresponding bit in optsflag. When omitted, + * the application (for read_structure) or plugin (for write_structure) + * must be able to supply default values if the missing parameters are + * part of its internal data structure. + * Note that it is not possible to specify coordinates with this structure. + * This is intentional; all coordinate I/O is done with the read_timestep and + * write_timestep functions. + */ + +/** + * Per-atom attributes and information. + */ +typedef struct { + /* these fields absolutely must be set or initialized to empty */ + char name[16]; /**< required atom name string */ + char type[16]; /**< required atom type string */ + char resname[8]; /**< required residue name string */ + int resid; /**< required integer residue ID */ + char segid[8]; /**< required segment name string, or "" */ + char chain[2]; /**< required chain name, or "" */ + + /* rest are optional; use optflags to specify what's present */ + char altloc[2]; /**< optional PDB alternate location code */ + char insertion[2]; /**< optional PDB insertion code */ + float occupancy; /**< optional occupancy value */ + float bfactor; /**< optional B-factor value */ + float mass; /**< optional mass value */ + float charge; /**< optional charge value */ + float radius; /**< optional radius value */ + int atomicnumber; /**< optional element atomic number */ +#if defined(DESRES_CTNUMBER) + int ctnumber; /**< mae ct block, 0-based, including meta */ +#endif +} molfile_atom_t; + +/*@{*/ +/** Plugin optional data field availability flag */ +#define MOLFILE_NOOPTIONS 0x0000 /**< no optional data */ +#define MOLFILE_INSERTION 0x0001 /**< insertion codes provided */ +#define MOLFILE_OCCUPANCY 0x0002 /**< occupancy data provided */ +#define MOLFILE_BFACTOR 0x0004 /**< B-factor data provided */ +#define MOLFILE_MASS 0x0008 /**< Atomic mass provided */ +#define MOLFILE_CHARGE 0x0010 /**< Atomic charge provided */ +#define MOLFILE_RADIUS 0x0020 /**< Atomic VDW radius provided */ +#define MOLFILE_ALTLOC 0x0040 /**< Multiple conformations present */ +#define MOLFILE_ATOMICNUMBER 0x0080 /**< Atomic element number provided */ +#define MOLFILE_BONDSSPECIAL 0x0100 /**< Only non-standard bonds provided */ +#if defined(DESRES_CTNUMBER) +#define MOLFILE_CTNUMBER 0x0200 /**< ctnumber provided */ +#endif +#define MOLFILE_BADOPTIONS 0xFFFFFFFF /**< Detect badly behaved plugins */ + +/*@}*/ + +/*@{*/ +/** Flags indicating availability of optional data fields + * for QM timesteps + */ +#define MOLFILE_QMTS_NOOPTIONS 0x0000 /**< no optional data */ +#define MOLFILE_QMTS_GRADIENT 0x0001 /**< energy gradients provided */ +#define MOLFILE_QMTS_SCFITER 0x0002 +/*@}*/ + +#if vmdplugin_ABIVERSION > 10 +typedef struct molfile_timestep_metadata { + unsigned int count; /**< total # timesteps; -1 if unknown */ + unsigned int avg_bytes_per_timestep; /** bytes per timestep */ + int has_velocities; /**< if timesteps have velocities */ +} molfile_timestep_metadata_t; +#endif + +/* + * Per-timestep atom coordinates and periodic cell information + */ +typedef struct { + float *coords; /**< coordinates of all atoms, arranged xyzxyzxyz */ +#if vmdplugin_ABIVERSION > 10 + float *velocities; /**< space for velocities of all atoms; same layout */ + /**< NULL unless has_velocities is set */ +#endif + + /*@{*/ + /** + * Unit cell specification of the form A, B, C, alpha, beta, gamma. + * notes: A, B, C are side lengths of the unit cell + * alpha = angle between b and c + * beta = angle between a and c + * gamma = angle between a and b + */ + float A, B, C, alpha, beta, gamma; + /*@}*/ + +#if vmdplugin_ABIVERSION > 10 + double physical_time; /**< physical time point associated with this frame */ +#endif + +#if defined(DESRES_READ_TIMESTEP2) + /* HACK to support generic trajectory information */ + double total_energy; + double potential_energy; + double kinetic_energy; + double extended_energy; + double force_energy; + double total_pressure; +#endif + +} molfile_timestep_t; + + +/** + * Metadata for volumetric datasets, read initially and used for subsequent + * memory allocations and file loading. + */ +typedef struct { + char dataname[256]; /**< name of volumetric data set */ + float origin[3]; /**< origin: origin of volume (x=0, y=0, z=0 corner */ + + /* + * x/y/z axis: + * These the three cell sides, providing both direction and length + * (not unit vectors) for the x, y, and z axes. In the simplest + * case, these would be <0,size,0> and <0,0,size) for + * an orthogonal cubic volume set. For other cell shapes these + * axes can be oriented non-orthogonally, and the parallelpiped + * may have different side lengths, not just a cube/rhombus. + */ + float xaxis[3]; /**< direction (and length) for X axis */ + float yaxis[3]; /**< direction (and length) for Y axis */ + float zaxis[3]; /**< direction (and length) for Z axis */ + + /* + * x/y/z size: + * Number of grid cells along each axis. This is _not_ the + * physical size of the box, this is the number of voxels in each + * direction, independent of the shape of the volume set. + */ + int xsize; /**< number of grid cells along the X axis */ + int ysize; /**< number of grid cells along the Y axis */ + int zsize; /**< number of grid cells along the Z axis */ + + int has_color; /**< flag indicating presence of voxel color data */ +} molfile_volumetric_t; + + + + +/************************************************************** + ************************************************************** + **** **** + **** Data structures for QM files **** + **** **** + ************************************************************** + **************************************************************/ + +#if vmdplugin_ABIVERSION > 9 + + +/* macros for the convergence status of a QM calculation. */ +#define MOLFILE_QMSTATUS_UNKNOWN -1 /* don't know yet */ +#define MOLFILE_QMSTATUS_OPT_CONV 0 /* optimization converged */ +#define MOLFILE_QMSTATUS_SCF_NOT_CONV 1 /* SCF convergence failed */ +#define MOLFILE_QMSTATUS_OPT_NOT_CONV 2 /* optimization not converged */ +#define MOLFILE_QMSTATUS_FILE_TRUNCATED 3 /* file was truncated */ + +/* macros describing the SCF method (SCFTYP in GAMESS) */ +#define MOLFILE_SCFTYPE_UNKNOWN -1 /* no info about the method */ +#define MOLFILE_SCFTYPE_NONE 0 /* calculation didn't make use of SCF */ +#define MOLFILE_SCFTYPE_RHF 1 /* restricted Hartree-Fock */ +#define MOLFILE_SCFTYPE_UHF 2 /* unrestricted Hartree-Fock */ +#define MOLFILE_SCFTYPE_ROHF 3 /* restricted open-shell Hartree-Fock */ +#define MOLFILE_SCFTYPE_GVB 4 /* generalized valence bond orbitals */ +#define MOLFILE_SCFTYPE_MCSCF 5 /* multi-configuration SCF */ +#define MOLFILE_SCFTYPE_FF 6 /* classical force-field based sim. */ + +/* macros describing the type of calculation (RUNTYP in GAMESS) */ +#define MOLFILE_RUNTYPE_UNKNOWN 0 /* single point run */ +#define MOLFILE_RUNTYPE_ENERGY 1 /* single point run */ +#define MOLFILE_RUNTYPE_OPTIMIZE 2 /* geometry optimization */ +#define MOLFILE_RUNTYPE_SADPOINT 3 /* saddle point search */ +#define MOLFILE_RUNTYPE_HESSIAN 4 /* Hessian/frequency calculation */ +#define MOLFILE_RUNTYPE_SURFACE 5 /* potential surface scan */ +#define MOLFILE_RUNTYPE_GRADIENT 6 /* energy gradient calculation */ +#define MOLFILE_RUNTYPE_MEX 7 /* minimum energy crossing */ +#define MOLFILE_RUNTYPE_DYNAMICS 8 /* Any type of molecular dynamics + * e.g. Born-Oppenheimer, Car-Parinello, + * or classical MD */ +#define MOLFILE_RUNTYPE_PROPERTIES 9 /* Properties were calculated from a + * wavefunction that was read from file */ + + +/** + * Sizes of various QM-related, timestep independent data arrays + * which must be allocated by the caller (VMD) so that the plugin + * can fill in the arrays with data. + */ +typedef struct { + /* hessian data */ + int nimag; /**< number of imaginary modes */ + int nintcoords; /**< number internal coordinates */ + int ncart; /**< number cartesian coordinates */ + + /* orbital/basisset data */ + int num_basis_funcs; /**< number of uncontracted basis functions in basis array */ + int num_basis_atoms; /**< number of atoms in basis set */ + int num_shells; /**< total number of atomic shells */ + int wavef_size; /**< size of the wavefunction + * i.e. size of secular eq. or + * # of cartesian contracted + * gaussian basis functions */ + + /* everything else */ + int have_sysinfo; + int have_carthessian; /**< hessian in cartesian coords available */ + int have_inthessian; /**< hessian in internal coords available */ + int have_normalmodes; /**< normal modes available */ +} molfile_qm_metadata_t; + + +/** + * QM run info. Parameters that stay unchanged during a single file. + */ +typedef struct { + int nproc; /**< number of processors used. */ + int memory; /**< amount of memory used in Mbyte. */ + int runtype; /**< flag indicating the calculation method. */ + int scftype; /**< SCF type: RHF, UHF, ROHF, GVB or MCSCF wfn. */ + int status; /**< indicates wether SCF and geometry optimization + * have converged properly. */ + int num_electrons; /**< number of electrons. XXX: can be fractional in some DFT codes */ + int totalcharge; /**< total charge of system. XXX: can be fractional in some DFT codes */ + int num_occupied_A; /**< number of occupied alpha orbitals */ + int num_occupied_B; /**< number of occupied beta orbitals */ + + double *nuc_charge; /**< array(natom) containing the nuclear charge of atom i */ + + char basis_string[MOLFILE_BUFSIZ]; /**< basis name as "nice" string. */ + char runtitle[MOLFILE_BIGBUFSIZ]; /**< title of run. */ + char geometry[MOLFILE_BUFSIZ]; /**< type of provided geometry, XXX: remove? + * e.g. UNIQUE, ZMT, CART, ... */ + char version_string[MOLFILE_BUFSIZ]; /**< QM code version information. */ +} molfile_qm_sysinfo_t; + + +/** + * Data for QM basis set + */ +typedef struct { + int *num_shells_per_atom; /**< number of shells per atom */ + int *num_prim_per_shell; /**< number of shell primitives shell */ + + float *basis; /**< contraction coeffients and exponents for + * the basis functions in the form + * {exp(1), c-coeff(1), exp(2), c-coeff(2), ...}; + * array size = 2*num_basis_funcs + * The basis must NOT be normalized. */ + int *atomic_number; /**< atomic numbers (chem. element) of atoms in basis set */ + int *angular_momentum; /**< 3 ints per wave function coefficient do describe the + * cartesian components of the angular momentum. + * E.g. S={0 0 0}, Px={1 0 0}, Dxy={1 1 0}, or Fyyz={0 2 1}. + */ + int *shell_types; /**< type for each shell in basis */ +} molfile_qm_basis_t; + + +/** + * Data from QM Hessian/normal mode runs + * + * A noteworthy comment from one of Axel's emails: + * The molfile_qm_hessian_t, I'd rename to molfile_hessian_t (one + * can do vibrational analysis without QM) and would make this a + * completely separate entity. This could then be also used to + * read in data from, say, principal component analysis or normal + * mode analysis and VMD could contain code to either project a + * trajectory on the contained eigenvectors or animate them and + * so on. There is a bunch of possible applications... + */ +typedef struct { + double *carthessian; /**< hessian matrix in cartesian coordinates (ncart)*(ncart) + * as a single array of doubles (row(1), ...,row(natoms)) */ + int *imag_modes; /**< list(nimag) of imaginary modes */ + double *inthessian; /**< hessian matrix in internal coordinates + * (nintcoords*nintcoords) as a single array of + * doubles (row(1), ...,row(nintcoords)) */ + float *wavenumbers; /**< array(ncart) of wavenumbers of normal modes */ + float *intensities; /**< array(ncart) of intensities of normal modes */ + float *normalmodes; /**< matrix(ncart*ncart) of normal modes */ +} molfile_qm_hessian_t; + + +/** + * QM related information that is timestep independent + */ +typedef struct { + molfile_qm_sysinfo_t run; /* system info */ + molfile_qm_basis_t basis; /* basis set info */ + molfile_qm_hessian_t hess; /* hessian info */ +} molfile_qm_t; + + + +/** + * Enumeration of all of the wavefunction types that can be read + * from QM file reader plugins. + * + * CANON = canonical (i.e diagonalized) wavefunction + * GEMINAL = GVB-ROHF geminal pairs + * MCSCFNAT = Multi-Configuration SCF natural orbitals + * MCSCFOPT = Multi-Configuration SCF optimized orbitals + * CINATUR = Configuration-Interaction natural orbitals + * BOYS = Boys localization + * RUEDEN = Ruedenberg localization + * PIPEK = Pipek-Mezey population localization + * + * NBO related localizations: + * -------------------------- + * NAO = Natural Atomic Orbitals + * PNAO = pre-orthogonal NAOs + * NBO = Natural Bond Orbitals + * PNBO = pre-orthogonal NBOs + * NHO = Natural Hybrid Orbitals + * PNHO = pre-orthogonal NHOs + * NLMO = Natural Localized Molecular Orbitals + * PNLMO = pre-orthogonal NLMOs + * + * UNKNOWN = Use this for any type not listed here + * You can use the string field for description + */ +enum molfile_qm_wavefunc_type { + MOLFILE_WAVE_CANON, MOLFILE_WAVE_GEMINAL, + MOLFILE_WAVE_MCSCFNAT, MOLFILE_WAVE_MCSCFOPT, + MOLFILE_WAVE_CINATUR, + MOLFILE_WAVE_PIPEK, MOLFILE_WAVE_BOYS, MOLFILE_WAVE_RUEDEN, + MOLFILE_WAVE_NAO, MOLFILE_WAVE_PNAO, MOLFILE_WAVE_NHO, + MOLFILE_WAVE_PNHO, MOLFILE_WAVE_NBO, MOLFILE_WAVE_PNBO, + MOLFILE_WAVE_PNLMO, MOLFILE_WAVE_NLMO, MOLFILE_WAVE_MOAO, + MOLFILE_WAVE_NATO, MOLFILE_WAVE_UNKNOWN +}; + + +/** + * Enumeration of all of the supported QM related charge + * types + */ +enum molfile_qm_charge_type { + MOLFILE_QMCHARGE_UNKNOWN, + MOLFILE_QMCHARGE_MULLIKEN, MOLFILE_QMCHARGE_LOWDIN, + MOLFILE_QMCHARGE_ESP, MOLFILE_QMCHARGE_NPA +}; + + + +/** + * Sizes of various QM-related, per-timestep data arrays + * which must be allocated by the caller (VMD) so that the plugin + * can fill in the arrays with data. + */ +typedef struct molfile_qm_timestep_metadata { + unsigned int count; /**< total # timesteps; -1 if unknown */ + unsigned int avg_bytes_per_timestep; /**< bytes per timestep */ + int has_gradient; /**< if timestep contains gradient */ + int num_scfiter; /**< # scf iterations for this ts */ + int num_orbitals_per_wavef[MOLFILE_MAXWAVEPERTS]; /**< # orbitals for each wavefunction */ + int has_orben_per_wavef[MOLFILE_MAXWAVEPERTS]; /**< orbital energy flags */ + int has_occup_per_wavef[MOLFILE_MAXWAVEPERTS]; /**< orbital occupancy flags */ + int num_wavef ; /**< # wavefunctions in this ts */ + int wavef_size; /**< size of one wavefunction + * (# of gaussian basis fctns) */ + int num_charge_sets; /**< # of charge values per atom */ +} molfile_qm_timestep_metadata_t; + + +/** + * QM wavefunction + */ +typedef struct { + int type; /**< MOLFILE_WAVE_CANON, MOLFILE_WAVE_MCSCFNAT, ... */ + int spin; /**< 1 for alpha, -1 for beta */ + int excitation; /**< 0 for ground state, 1,2,3,... for excited states */ + int multiplicity; /**< spin multiplicity of the state, zero if unknown */ + char info[MOLFILE_BUFSIZ]; /**< string for additional type info */ + + double energy; /**< energy of the electronic state. + * i.e. HF-SCF energy, CI state energy, + * MCSCF energy, etc. */ + + float *wave_coeffs; /**< expansion coefficients for wavefunction in the + * form {orbital1(c1),orbital1(c2),.....,orbitalM(cN)} */ + float *orbital_energies; /**< list of orbital energies for wavefunction */ + float *occupancies; /**< orbital occupancies */ + int *orbital_ids; /**< orbital ID numbers; If NULL then VMD will + * assume 1,2,3,...num_orbs. */ +} molfile_qm_wavefunction_t; + + +/** + * QM per trajectory timestep info + * Note that each timestep can contain multiple wavefunctions. + */ +typedef struct { + molfile_qm_wavefunction_t *wave; /**< array of wavefunction objects */ + float *gradient; /**< force on each atom (=gradient of energy) */ + + double *scfenergies; /**< energies from the SCF cycles */ + double *charges; /**< per-atom charges */ + int *charge_types; /**< type of each charge set */ +} molfile_qm_timestep_t; + + +#endif + +/************************************************************** + **************************************************************/ + + + + +/** + * Enumeration of all of the supported graphics objects that can be read + * from graphics file reader plugins. + */ +enum molfile_graphics_type { + MOLFILE_POINT, MOLFILE_TRIANGLE, MOLFILE_TRINORM, MOLFILE_NORMS, + MOLFILE_LINE, MOLFILE_CYLINDER, MOLFILE_CAPCYL, MOLFILE_CONE, + MOLFILE_SPHERE, MOLFILE_TEXT, MOLFILE_COLOR, MOLFILE_TRICOLOR +}; + +/** + * Individual graphics object/element data + */ +typedef struct { + int type; /* One of molfile_graphics_type */ + int style; /* A general style parameter */ + float size; /* A general size parameter */ + float data[9]; /* All data for the element */ +} molfile_graphics_t; + + +/* + * Types for raw graphics elements stored in files. Data for each type + * should be stored by the plugin as follows: + +type data style size +---- ---- ----- ---- +point x, y, z pixel size +triangle x1,y1,z1,x2,y2,z2,x3,y3,z3 +trinorm x1,y1,z1,x2,y2,z2,x3,y3,z3 + the next array element must be NORMS +tricolor x1,y1,z1,x2,y2,z2,x3,y3,z3 + the next array elements must be NORMS + the following element must be COLOR, with three RGB triples +norms x1,y1,z1,x2,y2,z2,x3,y3,z3 +line x1,y1,z1,x2,y2,z2 0=solid pixel width + 1=stippled +cylinder x1,y1,z1,x2,y2,z2 resolution radius +capcyl x1,y1,z1,x2,y2,z2 resolution radius +sphere x1,y1,z1 resolution radius +text x, y, z, up to 24 bytes of text pixel size +color r, g, b +*/ + + +/** + * Main file reader API. Any function in this struct may be NULL + * if not implemented by the plugin; the application checks this to determine + * what functionality is present in the plugin. + */ +typedef struct { + /** + * Required header + */ + vmdplugin_HEAD + + /** + * Filename extension for this file type. May be NULL if no filename + * extension exists and/or is known. For file types that match several + * common extensions, list them in a comma separated list such as: + * "pdb,ent,foo,bar,baz,ban" + * The comma separated list will be expanded when filename extension matching + * is performed. If multiple plugins solicit the same filename extensions, + * the one that lists the extension earliest in its list is selected. In the + * case of a "tie", the first one tried/checked "wins". + */ + const char *filename_extension; + + /** + * Try to open the file for reading. Return an opaque handle, or NULL on + * failure. Set the number of atoms; if the number of atoms cannot be + * determined, set natoms to MOLFILE_NUMATOMS_UNKNOWN. + * Filetype should be the name under which this plugin was registered; + * this is provided so that plugins can provide the same function pointer + * to handle multiple file types. + */ + void *(* open_file_read)(const char *filepath, const char *filetype, + int *natoms); + + /** + * Read molecular structure from the given file handle. atoms is allocated + * by the caller and points to space for natoms. + * On success, place atom information in the passed-in pointer. + * optflags specifies which optional fields in the atoms will be set by + * the plugin. + */ + int (*read_structure)(void *, int *optflags, molfile_atom_t *atoms); + + /** + * Read bond information for the molecule. On success the arrays from + * and to should point to the (one-based) indices of bonded atoms. + * Each unique bond should be specified only once, so file formats that list + * bonds twice will need post-processing before the results are returned to + * the caller. + * If the plugin provides bond information, but the file loaded doesn't + * actually contain any bond info, the nbonds parameter should be + * set to 0 and from/to should be set to NULL to indicate that no bond + * information was actually present, and automatic bond search should be + * performed. + * + * If the plugin provides bond order information, the bondorder array + * will contain the bond order for each from/to pair. If not, the bondorder + * pointer should be set to NULL, in which case the caller will provide a + * default bond order value of 1.0. + * + * If the plugin provides bond type information, the bondtype array + * will contain the bond type index for each from/to pair. These numbers + * are consecutive integers starting from 0. + * the bondtypenames list, contains the corresponding names, if available, + * as a NULL string terminated list. nbondtypes is provided for convenience + * and consistency checking. + * + * These arrays must be freed by the plugin in the close_file_read function. + * This function can be called only after read_structure(). + * Return MOLFILE_SUCCESS if no errors occur. + */ +#if vmdplugin_ABIVERSION > 14 + int (*read_bonds)(void *, int *nbonds, int **from, int **to, float **bondorder, + int **bondtype, int *nbondtypes, char ***bondtypename); +#else + int (*read_bonds)(void *, int *nbonds, int **from, int **to, float **bondorder); +#endif + + /** + * XXX this function will be augmented and possibly superceded by a + * new QM-capable version named read_timestep(), when finished. + * + * Read the next timestep from the file. Return MOLFILE_SUCCESS, or + * MOLFILE_EOF on EOF. If the molfile_timestep_t argument is NULL, then + * the frame should be skipped. Otherwise, the application must prepare + * molfile_timestep_t by allocating space in coords for the corresponding + * number of coordinates. + * The natoms parameter exists because some coordinate file formats + * (like CRD) cannot determine for themselves how many atoms are in a + * timestep; the app must therefore obtain this information elsewhere + * and provide it to the plugin. + */ + int (* read_next_timestep)(void *, int natoms, molfile_timestep_t *); + + /** + * Close the file and release all data. The handle cannot be reused. + */ + void (* close_file_read)(void *); + + /** + * Open a coordinate file for writing using the given header information. + * Return an opaque handle, or NULL on failure. The application must + * specify the number of atoms to be written. + * filetype should be the name under which this plugin was registered. + */ + void *(* open_file_write)(const char *filepath, const char *filetype, + int natoms); + + /** + * Write structure information. Return success. + */ + int (* write_structure)(void *, int optflags, const molfile_atom_t *atoms); + + /** + * Write a timestep to the coordinate file. Return MOLFILE_SUCCESS if no + * errors occur. If the file contains structure information in each + * timestep (like a multi-entry PDB), it will have to cache the information + * from the initial calls from write_structure. + */ + int (* write_timestep)(void *, const molfile_timestep_t *); + + /** + * Close the file and release all data. The handle cannot be reused. + */ + void (* close_file_write)(void *); + + /** + * Retrieve metadata pertaining to volumetric datasets in this file. + * Set nsets to the number of volumetric data sets, and set *metadata + * to point to an array of molfile_volumetric_t. The array is owned by + * the plugin and should be freed by close_file_read(). The application + * may call this function any number of times. + */ + int (* read_volumetric_metadata)(void *, int *nsets, + molfile_volumetric_t **metadata); + + /** + * Read the specified volumetric data set into the space pointed to by + * datablock. The set is specified with a zero-based index. The space + * allocated for the datablock must be equal to + * xsize * ysize * zsize. No space will be allocated for colorblock + * unless has_color is nonzero; in that case, colorblock should be + * filled in with three RGB floats per datapoint. + */ + int (* read_volumetric_data)(void *, int set, float *datablock, + float *colorblock); + + /** + * Read raw graphics data stored in this file. Return the number of data + * elements and the data itself as an array of molfile_graphics_t in the + * pointer provided by the application. The plugin is responsible for + * freeing the data when the file is closed. + */ + int (* read_rawgraphics)(void *, int *nelem, const molfile_graphics_t **data); + + /** + * Read molecule metadata such as what database (if any) this file/data + * came from, what the accession code for the database is, textual remarks + * and other notes pertaining to the contained structure/trajectory/volume + * and anything else that's informative at the whole file level. + */ + int (* read_molecule_metadata)(void *, molfile_metadata_t **metadata); + + /** + * Write bond information for the molecule. The arrays from + * and to point to the (one-based) indices of bonded atoms. + * Each unique bond will be specified only once by the caller. + * File formats that list bonds twice will need to emit both the + * from/to and to/from versions of each. + * This function must be called before write_structure(). + * + * Like the read_bonds() routine, the bondorder pointer is set to NULL + * if the caller doesn't have such information, in which case the + * plugin should assume a bond order of 1.0 if the file format requires + * bond order information. + * + * Support for bond types follows the bondorder rules. bondtype is + * an integer array of the size nbonds that contains the bond type + * index (consecutive integers starting from 0) and bondtypenames + * contain the corresponding strings, in case the naming/numbering + * scheme is different from the index numbers. + * if the pointers are set to NULL, then this information is not available. + * bondtypenames can only be used of bondtypes is also given. + * Return MOLFILE_SUCCESS if no errors occur. + */ +#if vmdplugin_ABIVERSION > 14 + int (* write_bonds)(void *, int nbonds, int *from, int *to, float *bondorder, + int *bondtype, int nbondtypes, char **bondtypename); +#else + int (* write_bonds)(void *, int nbonds, int *from, int *to, float *bondorder); +#endif + +#if vmdplugin_ABIVERSION > 9 + /** + * Write the specified volumetric data set into the space pointed to by + * datablock. The * allocated for the datablock must be equal to + * xsize * ysize * zsize. No space will be allocated for colorblock + * unless has_color is nonzero; in that case, colorblock should be + * filled in with three RGB floats per datapoint. + */ + int (* write_volumetric_data)(void *, molfile_volumetric_t *metadata, + float *datablock, float *colorblock); + +#if vmdplugin_ABIVERSION > 15 + /** + * Read in Angles, Dihedrals, Impropers, and Cross Terms and optionally types. + * (Cross terms pertain to the CHARMM/NAMD CMAP feature) + */ + int (* read_angles)(void *handle, int *numangles, int **angles, int **angletypes, + int *numangletypes, char ***angletypenames, int *numdihedrals, + int **dihedrals, int **dihedraltypes, int *numdihedraltypes, + char ***dihedraltypenames, int *numimpropers, int **impropers, + int **impropertypes, int *numimpropertypes, char ***impropertypenames, + int *numcterms, int **cterms, int *ctermcols, int *ctermrows); + + /** + * Write out Angles, Dihedrals, Impropers, and Cross Terms + * (Cross terms pertain to the CHARMM/NAMD CMAP feature) + */ + int (* write_angles)(void *handle, int numangles, const int *angles, const int *angletypes, + int numangletypes, const char **angletypenames, int numdihedrals, + const int *dihedrals, const int *dihedraltypes, int numdihedraltypes, + const char **dihedraltypenames, int numimpropers, + const int *impropers, const int *impropertypes, int numimpropertypes, + const char **impropertypenames, int numcterms, const int *cterms, + int ctermcols, int ctermrows); +#else + /** + * Read in Angles, Dihedrals, Impropers, and Cross Terms + * Forces are in Kcal/mol + * (Cross terms pertain to the CHARMM/NAMD CMAP feature, forces are given + * as a 2-D matrix) + */ + int (* read_angles)(void *, + int *numangles, int **angles, double **angleforces, + int *numdihedrals, int **dihedrals, double **dihedralforces, + int *numimpropers, int **impropers, double **improperforces, + int *numcterms, int **cterms, + int *ctermcols, int *ctermrows, double **ctermforces); + + /** + * Write out Angles, Dihedrals, Impropers, and Cross Terms + * Forces are in Kcal/mol + * (Cross terms pertain to the CHARMM/NAMD CMAP feature, forces are given + * as a 2-D matrix) + */ + int (* write_angles)(void *, + int numangles, const int *angles, const double *angleforces, + int numdihedrals, const int *dihedrals, const double *dihedralforces, + int numimpropers, const int *impropers, const double *improperforces, + int numcterms, const int *cterms, + int ctermcols, int ctermrows, const double *ctermforces); +#endif + + + /** + * Retrieve metadata pertaining to timestep independent + * QM datasets in this file. + * + * The metadata are the sizes of the QM related data structure + * arrays that will be populated by the plugin when + * read_qm_rundata() is called. Since the allocation of these + * arrays is done by VMD rather than the plugin, VMD needs to + * know the sizes beforehand. Consequently read_qm_metadata() + * has to be called before read_qm_rundata(). + */ + int (* read_qm_metadata)(void *, molfile_qm_metadata_t *metadata); + + + /** + * Read timestep independent QM data. + * + * Typical data that are defined only once per trajectory are + * general info about the calculation (such as the used method), + * the basis set and normal modes. + * The data structures to be populated must have been allocated + * before by VMD according to sizes obtained through + * read_qm_metadata(). + */ + int (* read_qm_rundata)(void *, molfile_qm_t *qmdata); + + + /** + * Read the next timestep from the file. Return MOLFILE_SUCCESS, or + * MOLFILE_EOF on EOF. If the molfile_timestep_t or molfile_qm_metadata_t + * arguments are NULL, then the coordinate or qm data should be skipped. + * Otherwise, the application must prepare molfile_timestep_t and + * molfile_qm_timestep_t by allocating space for the corresponding + * number of coordinates, orbital wavefunction coefficients, etc. + * Since it is common for users to want to load only the final timestep + * data from a QM run, the application may provide any combination of + * valid, or NULL pointers for the molfile_timestep_t and + * molfile_qm_timestep_t parameters, depending on what information the + * user is interested in. + * The natoms and qm metadata parameters exist because some file formats + * cannot determine for themselves how many atoms etc are in a + * timestep; the app must therefore obtain this information elsewhere + * and provide it to the plugin. + */ + int (* read_timestep)(void *, int natoms, molfile_timestep_t *, + molfile_qm_metadata_t *, molfile_qm_timestep_t *); +#endif + +#if vmdplugin_ABIVERSION > 10 + int (* read_timestep_metadata)(void *, molfile_timestep_metadata_t *); +#endif +#if vmdplugin_ABIVERSION > 11 + int (* read_qm_timestep_metadata)(void *, molfile_qm_timestep_metadata_t *); +#endif + +#if defined(DESRES_READ_TIMESTEP2) + /** + * Read a specified timestep! + */ + int (* read_timestep2)(void *, molfile_ssize_t index, molfile_timestep_t *); + + /** + * write up to count times beginning at index start into the given + * space. Return the number read, or -1 on error. + */ + molfile_ssize_t (* read_times)( void *, + molfile_ssize_t start, + molfile_ssize_t count, + double * times ); +#endif + +#if vmdplugin_ABIVERSION > 13 + /** + * Console output, READ-ONLY function pointer. + * Function pointer that plugins can use for printing to the host + * application's text console. This provides a clean way for plugins + * to send message strings back to the calling application, giving the + * caller the ability to prioritize, buffer, and redirect console messages + * to an appropriate output channel, window, etc. This enables the use of + * graphical consoles like TkCon without losing console output from plugins. + * If the function pointer is NULL, no console output service is provided + * by the calling application, and the output should default to stdout + * stream. If the function pointer is non-NULL, all output will be + * subsequently dealt with by the calling application. + * + * XXX this should really be put into a separate block of + * application-provided read-only function pointers for any + * application-provided services + */ + int (* cons_fputs)(const int, const char*); +#endif + +} molfile_plugin_t; + +#endif + diff --git a/src/USER-MOLFILE/vmdplugin.h b/src/USER-MOLFILE/vmdplugin.h new file mode 100644 index 0000000000..f58a5e435b --- /dev/null +++ b/src/USER-MOLFILE/vmdplugin.h @@ -0,0 +1,191 @@ +/*************************************************************************** + *cr + *cr (C) Copyright 1995-2006 The Board of Trustees of the + *cr University of Illinois + *cr All Rights Reserved + *cr + ***************************************************************************/ + +/*************************************************************************** + * RCS INFORMATION: + * + * $RCSfile: vmdplugin.h,v $ + * $Author: johns $ $Locker: $ $State: Exp $ + * $Revision: 1.32 $ $Date: 2009/02/24 05:12:35 $ + * + ***************************************************************************/ + +/** @file + * This header must be included by every VMD plugin library. It defines the + * API for every plugin so that VMD can organize the plugins it finds. + */ + +#ifndef VMD_PLUGIN_H +#define VMD_PLUGIN_H + + +/* + * Preprocessor tricks to make it easier for us to redefine the names of + * functions when building static plugins. + */ +#if !defined(VMDPLUGIN) +/** + * macro defining VMDPLUGIN if it hasn't already been set to the name of + * a static plugin that is being compiled. This is the catch-all case. + */ +#define VMDPLUGIN vmdplugin +#endif +/** concatenation macro, joins args x and y together as a single string */ +#define xcat(x, y) cat(x, y) +/** concatenation macro, joins args x and y together as a single string */ +#define cat(x, y) x ## y + +/* + * macros to correctly define plugin function names depending on whether + * the plugin is being compiled for static linkage or dynamic loading. + * When compiled for static linkage, each plugin needs to have unique + * function names for all of its entry points. When compiled for dynamic + * loading, the plugins must name their entry points consistently so that + * the plugin loading mechanism can find the register, register_tcl, init, + * and fini routines via dlopen() or similar operating system interfaces. + */ +/*@{*/ +/** Macro names entry points correctly for static linkage or dynamic loading */ +#define VMDPLUGIN_register xcat(VMDPLUGIN, _register) +#define VMDPLUGIN_register_tcl xcat(VMDPLUGIN, _register_tcl) +#define VMDPLUGIN_init xcat(VMDPLUGIN, _init) +#define VMDPLUGIN_fini xcat(VMDPLUGIN, _fini) +/*@}*/ + + +/** "WIN32" is defined on both WIN32 and WIN64 platforms... */ +#if (defined(WIN32)) +#define WIN32_LEAN_AND_MEAN +#include + +#if !defined(STATIC_PLUGIN) +#if defined(VMDPLUGIN_EXPORTS) +/** + * Only define DllMain for plugins, not in VMD or in statically linked plugins + * VMDPLUGIN_EXPORTS is only defined when compiling dynamically loaded plugins + */ +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + return TRUE; +} + +#define VMDPLUGIN_API __declspec(dllexport) +#else +#define VMDPLUGIN_API __declspec(dllimport) +#endif /* VMDPLUGIN_EXPORTS */ +#else /* ! STATIC_PLUGIN */ +#define VMDPLUGIN_API +#endif /* ! STATIC_PLUGIN */ +#else +/** If we're not compiling on Windows, then this macro is defined empty */ +#define VMDPLUGIN_API +#endif + +/** define plugin linkage correctly for both C and C++ based plugins */ +#ifdef __cplusplus +#define VMDPLUGIN_EXTERN extern "C" VMDPLUGIN_API +#else +#define VMDPLUGIN_EXTERN extern VMDPLUGIN_API +#endif /* __cplusplus */ + +/* + * Plugin API functions start here + */ + + +/** + * Init routine: called the first time the library is loaded by the + * application and before any other API functions are referenced. + * Return 0 on success. + */ +VMDPLUGIN_EXTERN int VMDPLUGIN_init(void); + +/** + * Macro for creating a struct header used in all plugin structures. + * + * This header should be placed at the top of every plugin API definition + * so that it can be treated as a subtype of the base plugin type. + * + * abiversion: Defines the ABI for the base plugin type (not for other plugins) + * type: A string descriptor of the plugin type. + * name: A name for the plugin. + * author: A string identifier, possibly including newlines. + * Major and minor version. + * is_reentrant: Whether this library can be run concurrently with itself. + */ +#define vmdplugin_HEAD \ + int abiversion; \ + const char *type; \ + const char *name; \ + const char *prettyname; \ + const char *author; \ + int majorv; \ + int minorv; \ + int is_reentrant; + +/** + * Typedef for generic plugin header, individual plugins can + * make their own structures as long as the header info remains + * the same as the generic plugin header, most easily done by + * using the vmdplugin_HEAD macro. + */ +typedef struct { + vmdplugin_HEAD +} vmdplugin_t; + +/** + * Use this macro to initialize the abiversion member of each plugin + */ +#define vmdplugin_ABIVERSION 16 + +/*@{*/ +/** Use this macro to indicate a plugin's thread-safety at registration time */ +#define VMDPLUGIN_THREADUNSAFE 0 +#define VMDPLUGIN_THREADSAFE 1 +/*@}*/ + +/*@{*/ +/** Error return code for use in the plugin registration and init functions */ +#define VMDPLUGIN_SUCCESS 0 +#define VMDPLUGIN_ERROR -1 +/*@}*/ + +/** + * Function pointer typedef for register callback functions + */ +typedef int (*vmdplugin_register_cb)(void *, vmdplugin_t *); + +/** + * Allow the library to register plugins with the application. + * The callback should be called using the passed-in void pointer, which + * should not be interpreted in any way by the library. Each vmdplugin_t + * pointer passed to the application should point to statically-allocated + * or heap-allocated memory and should never be later modified by the plugin. + * Applications must be permitted to retain only a copy of the the plugin + * pointer, without making any deep copy of the items in the struct. + */ +VMDPLUGIN_EXTERN int VMDPLUGIN_register(void *, vmdplugin_register_cb); + +/** + * Allow the library to register Tcl extensions. + * This API is optional; if found by dlopen, it will be called after first + * calling init and register. + */ +VMDPLUGIN_EXTERN int VMDPLUGIN_register_tcl(void *, void *tcl_interp, + vmdplugin_register_cb); + +/** + * The Fini method is called when the application will no longer use + * any plugins in the library. + */ +VMDPLUGIN_EXTERN int VMDPLUGIN_fini(void); + +#endif /* VMD_PLUGIN_H */