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

CoorPluginData.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: CoorPluginData.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.34 $       $Date: 2020/06/11 08:17:38 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Interface code that manages loading and saving of coordinate data via 
00019  *  plugin interfaces.  Uses MolFilePlugin to do the file loading.
00020  ***************************************************************************/
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 
00026 #include "CoorPluginData.h"
00027 #include "MolFilePlugin.h"
00028 #include "Inform.h"
00029 #include "Molecule.h"
00030 #include "WKFUtils.h"
00031 
00032 CoorPluginData::CoorPluginData(const char *nm, Molecule *m, MolFilePlugin *p,
00033     int input, int first, int stride, int last, const int *sel) 
00034 : CoorData(nm), is_input(input), begFrame(first), frameSkip(stride), 
00035   endFrame(last) {
00036 
00038   selection = NULL;
00039 
00041   plugin = NULL;
00042 
00044   tm=NULL;
00045 
00046   // ensure ts_page_alignment flag is cleared by default
00047   ts_page_align_sz=0;
00048 
00050   kbytesperframe=0;
00051   totalframes=0;
00052 
00053   // make sure frame data is correct
00054   if(begFrame < 0)
00055     begFrame = 0;
00056   if(endFrame < begFrame)
00057     endFrame = (-1);
00058   if(frameSkip <= 0)
00059     frameSkip = 1;
00060   recentFrame = -1;
00061 
00062   // make sure frame data is valid
00063   if(!m || (!is_input && 
00064               ( m->numframes() < begFrame || endFrame >= m->numframes() ) 
00065            ) ) {
00066     msgErr << "Illegal frames requested for coordinate file I/O" << sendmsg;
00067     return;
00068   }
00069   if (is_input) {
00070     // Checks for and reject attempts to use selections when reading
00071     // coordinates.  The most useful thing to do would be to allow coordinate
00072     // files to contain whatever number of atoms you want, and then use the
00073     // selection to filter those atoms.  However, one could go a number of ways
00074     // with this.  Should the selection be reparsed using the structure and/or
00075     // coordinate data in the new file in order to determine which atoms to
00076     // read, or should one simply use the already-computed atom indices?  I can
00077     // think of situations where both of those behaviors would be desirable.
00078     if (sel) {
00079       msgErr << "Internal error: cannot read selection of coordinates"
00080              << sendmsg;
00081       return;
00082     }
00083     // make sure that the number of atoms in the coordinate file is either valid
00084     // or unknown.
00085     if (p->natoms() != m->nAtoms) {
00086       if (p->natoms() == -1) {
00087         p->set_natoms(m->nAtoms);
00088       } else {
00089         msgErr << "Incorrect number of atoms (" << p->natoms() << ") in" 
00090                << sendmsg;
00091         msgErr << "coordinate file " << nm << sendmsg;
00092         msgErr << "Mismatch between existing molecule or structure file atom count and coordinate or trajectory file atom count." << sendmsg;
00093         return;
00094       } 
00095     } 
00096   }
00097 
00098   // make plugin and selection information valid
00099   plugin = p;
00100   if (sel) {
00101     selection = new int[m->nAtoms];
00102     memcpy(selection, sel, m->nAtoms * sizeof(int));
00103   }
00104 
00105   tm=wkf_timer_create();
00106   wkf_timer_start(tm);
00107 
00108   // If this is output, write the structure now.  
00109   if (!is_input && plugin->can_write_structure()) {
00110     if (plugin->write_structure(m, selection) == MOLFILE_SUCCESS) {
00111       totalframes++;
00112     } else {
00113       plugin = NULL;
00114     }
00115   }
00116 
00117   if (is_input) {
00118     kbytesperframe = (long(p->natoms()) * 12L) / 1024L;
00119   } else {
00120     kbytesperframe = (long(m->nAtoms) * 12L) / 1024L;
00121   }
00122 
00123   // Check if VMD has to use page-aligned memory allocations for
00124   // timestep data, to allow for fast kernel-bypass unbuffered I/O APIs
00125   if (plugin->can_read_pagealigned_timesteps()) {
00126 #if vmdplugin_ABIVERSION > 17
00127     ts_page_align_sz = plugin->read_timestep_pagealign_size();
00128 #else
00129 #if 1
00130     ts_page_align_sz = 1; // assume non-blocked I/O
00131 #else
00132     // Enable VMD to cope with hard-coded revs of jsplugin if we want
00133     ts_page_align_sz = MOLFILE_DIRECTIO_MAX_BLOCK_SIZE;
00134 #endif
00135 #endif
00136   } else {
00137     ts_page_align_sz = 1; // set page alignment flag to indicate normal I/O
00138   }
00139 }
00140 
00141 CoorPluginData::~CoorPluginData() {
00142   delete plugin;
00143   plugin = NULL;
00144 
00145   if (tm) {
00146     wkf_timer_destroy(tm);
00147     tm=NULL;
00148   }
00149 
00150   delete [] selection;
00151 }
00152 
00153 CoorData::CoorDataState CoorPluginData::next(Molecule *m) {
00154   if (!plugin) 
00155     return DONE;
00156 
00157   if (is_input) {
00158     if (recentFrame < 0) {
00159       recentFrame = 0;
00160       while (recentFrame < begFrame) {
00161         plugin->skip(m);
00162         recentFrame++;
00163       }
00164     } else {
00165       for (int i=1; i<frameSkip; i++) 
00166         plugin->skip(m);
00167       recentFrame += frameSkip;
00168     }
00169     if (endFrame < 0 || recentFrame <= endFrame) {
00170       Timestep *ts = plugin->next(m, ts_page_align_sz); 
00171       if (ts) {
00172         m->append_frame(ts);
00173         totalframes++;
00174         return NOTDONE;
00175       }
00176     }
00177   } else if (m->numframes() > 0) {  // output
00178     if (recentFrame < 0)
00179       recentFrame = begFrame;
00180     else
00181       recentFrame += frameSkip;
00182 
00183     // get next frame, and write to file
00184     if ((endFrame < 0 || recentFrame <= endFrame) 
00185         && m->numframes() > recentFrame) {
00186       Timestep *ts = m->get_frame(recentFrame);
00187       if (ts) {
00188         if (!plugin->write_timestep(ts, selection)) {
00189           totalframes++;
00190           return NOTDONE;
00191         } else {
00192           msgErr << "write_timestep returned nonzero" << sendmsg;
00193         }
00194       }      
00195     }
00196   }
00197 
00198   if (tm != NULL && totalframes > 0) {
00199     double iotime = wkf_timer_timenow(tm);
00200     // emit I/O stats if requested, or it took more than 3 seconds
00201     if ((getenv("VMDTSTIMER") != NULL) || (iotime > 3.0)) {
00202       float framerate = (float) (((double) totalframes) / iotime);
00203       char tmbuf[1024], frameratebuf[1024];
00204       sprintf(tmbuf, "%.1f", iotime);
00205       if (framerate > 10)
00206         sprintf(frameratebuf, "%.1f", framerate);
00207       else
00208         sprintf(frameratebuf, "%.2f", framerate);
00209       msgInfo << "Coordinate I/O rate " 
00210               << frameratebuf << " frames/sec, "
00211               << (int) ((totalframes / iotime) * (kbytesperframe / 1024.0)) 
00212               << " MB/sec, "
00213               << tmbuf << " sec" << sendmsg;
00214     }
00215   }
00216 
00217   // we're done; close file and stop reading/writing
00218   delete plugin;
00219   plugin = NULL;
00220   return DONE;
00221 }
00222 

Generated on Fri Mar 29 02:45:01 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002