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

Molecule.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: Molecule.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.92 $       $Date: 2019/01/17 21:21:00 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * Main Molecule objects, which contains all the capabilities necessary to
00020  * store, draw, and manipulate a molecule.  This adds to the functions of
00021  * DrawMolecule and BaseMolecule by adding routines to read and write various
00022  * coordinate files.
00023  *
00024  * Note: Other capabilities, such as writing structure files, mutations, etc.
00025  * should go into this level.
00026  *
00027  ***************************************************************************/
00028 
00029 #include "Molecule.h"
00030 #include "Inform.h"
00031 #include "DisplayDevice.h"
00032 #include "TextEvent.h"
00033 #include "VMDApp.h"
00034 #include "CommandQueue.h"
00035 #include "CoorData.h"
00036 
00038 
00039 Molecule::Molecule(const char *src, VMDApp *vmdapp, Displayable *d) 
00040   : DrawMolecule(vmdapp, d), coorIOFiles(8) {
00041 
00042   char *strPath = NULL, *strName = NULL;
00043   breakup_filename(src, &strPath, &strName);
00044   if (!strName) strName = stringdup("unknown");
00045 
00046   // set the molecule name
00047   moleculename = stringdup(strName);
00048   delete [] strPath;
00049   delete [] strName;
00050 }
00051 
00053 Molecule::~Molecule(void) {
00054   int i;
00055 
00056   // Disconnect this molecule from IMD, if it's active
00057   app->imd_disconnect(id());
00058 
00059   while(coorIOFiles.num() > 0) {
00060     delete coorIOFiles[0];
00061     coorIOFiles.remove(0);
00062   }
00063 
00064   if (moleculename)
00065     delete [] moleculename;
00066 
00067   for (i=0; i<fileList.num(); i++) {
00068     delete [] fileList[i];
00069   } 
00070   for (i=0; i<fileSpecList.num(); i++) {
00071     delete [] fileSpecList[i];
00072   } 
00073   for (i=0; i<typeList.num(); i++) {
00074     delete [] typeList[i];
00075   } 
00076   for (i=0; i<dbList.num(); i++) {
00077     delete [] dbList[i];
00078   } 
00079   for (i=0; i<accessionList.num(); i++) {
00080     delete [] accessionList[i];
00081   } 
00082   for (i=0; i<remarksList.num(); i++) {
00083     delete [] remarksList[i];
00084   } 
00085 }
00086 
00088 
00089 int Molecule::rename(const char *newname) {
00090   delete [] moleculename;
00091   moleculename = stringdup(newname);
00092   return 1;
00093 }
00094 
00095 void Molecule::add_coor_file(CoorData *data) {
00096   coorIOFiles.append(data);
00097 }
00098 
00099 void Molecule::close_coor_file(CoorData *data) {
00100   // remove file from list
00101   msgInfo << "Finished with coordinate file " << data->name << "." << sendmsg;
00102 
00103   // Must be appended, not run, because callbacks could delete the molecule!
00104   app->commandQueue->append(
00105     new TrajectoryReadEvent(id(), data->name)
00106   );
00107 
00108   delete data;
00109 }
00110 
00111 // cancel load/save of coordinate files
00112 // return number canceled
00113 int Molecule::cancel() {
00114   int retval = 0;
00115   while(coorIOFiles.num() > 0) {
00116     msgInfo << "Canceling load/save of file: " << coorIOFiles[0]->name 
00117             << sendmsg;
00118     delete coorIOFiles[0];
00119     coorIOFiles.remove(0);
00120     retval++;
00121   }
00122   return retval;
00123 }
00124 
00125 int Molecule::get_new_frames() {
00126   int newframes = 0;
00127 
00128   // add a new frame if there are frames available in the I/O queue
00129   if (next_frame())
00130     newframes = 1; 
00131 
00132   // If an IMD simulation is in progress, store the forces in the current
00133   // timestep and send them to the simulation.  Otherwise, just toss them.
00134   if (app->imd_connected(id())) {
00135     // Add persistent forces to regular forces
00136     force_indices.appendlist(&persistent_force_indices[0], persistent_force_indices.num());
00137     force_vectors.appendlist(&persistent_force_vectors[0], persistent_force_vectors.num());
00138 
00139     // Clear old forces out of the timestep
00140     Timestep *ts = current();
00141     if (ts && ts->force) {
00142       memset(ts->force, 0, 3L*nAtoms*sizeof(float));
00143     }
00144 
00145     // Check for atoms forced last time that didn't show up this time.
00146     // XXX order N^2 in number of applied forces; could be easily improved.
00147     // But N now is usually 1 or 2.
00148     ResizeArray<int> zero_force_indices;
00149     ResizeArray<float> zero_forces;
00150 
00151     int forcecnt = force_indices.num(); // save in local var for speed
00152 
00153     int ii;
00154     for(ii=0; ii<last_force_indices.num(); ii++) {
00155       int j;
00156       int index_missing=1;
00157       for (j=0; j<forcecnt; j++) {
00158         if (force_indices[j]==last_force_indices[ii]) {
00159           index_missing=0;
00160           break;
00161         }
00162       }
00163       if (index_missing) {
00164         // this one didn't show up this time
00165         zero_force_indices.append(last_force_indices[ii]);
00166         zero_forces.append3(0, 0, 0);
00167       }
00168     }
00169 
00170     if (zero_force_indices.num()) {
00171       // There some atoms forced last time that didn't show up this time.
00172       app->imd_sendforces(zero_force_indices.num(), &(zero_force_indices[0]),
00173                           &(zero_forces[0]));
00174     }
00175 
00176     // now clear the last forces so we don't send them again
00177     last_force_indices.clear();
00178 
00179     // Set/send forces if we got any
00180     if (forcecnt) {
00181       if (ts) {
00182         if (!ts->force) {
00183           ts->force = new float[3L*nAtoms];
00184           memset(ts->force, 0, 3L*nAtoms*sizeof(float));
00185         }
00186         for (int i=0; i<forcecnt; i++) {
00187           int ind = force_indices[i];
00188           ts->force[3L*ind  ] += force_vectors[3L*i  ];
00189           ts->force[3L*ind+1] += force_vectors[3L*i+1];
00190           ts->force[3L*ind+2] += force_vectors[3L*i+2];
00191         }
00192       }
00193       // XXX If we send multiple forces for the same atom, NAMD will keep only
00194       // the last force.  We therefore have to sum multiple contributions to the
00195       // same atom before sending.  Annoying.
00196       ResizeArray<float> summed_forces;
00197       int i;
00198       for (i=0; i<forcecnt; i++) {
00199         int ind = force_indices[i];
00200         summed_forces.append3(&ts->force[3L*ind]);
00201       }
00202       app->imd_sendforces(forcecnt, &(force_indices[0]), &(summed_forces[0]));
00203 
00204       // save the force indices before clearing them
00205       last_force_indices.appendlist(&force_indices[0], force_indices.num());
00206 
00207       // now clear the force indices
00208       force_indices.clear();
00209       force_vectors.clear();
00210     }
00211   }
00212 
00213   // Inform the top level class that background processing
00214   // is going on to prevent the CPU throttling code from activating
00215   if (newframes > 0)
00216     app->background_processing_set();
00217 
00218   return newframes;  
00219 }
00220 
00221 int Molecule::next_frame() {
00222   CoorData::CoorDataState state = CoorData::DONE;
00223 
00224   while (coorIOFiles.num() > 0) {
00225     // R/W'ing file, do frames until DONE is returned (then close)
00226     state = coorIOFiles[0]->next(this);
00227 
00228     if (state == CoorData::DONE) {
00229       close_coor_file(coorIOFiles[0]);
00230       coorIOFiles.remove(0);
00231     } else {
00232       break; // we got a frame, return to caller;
00233     }
00234   }
00235 
00236   return (state == CoorData::NOTDONE);
00237 }
00238 
00239 // prepare for drawing ... can do one or more of the following:
00240 //  - open a new file and start reading
00241 //  - continue reading an already open file
00242 //  - finish reading a file and close it
00243 //  - always add a new frame if there are frames available
00244 // when done, this then 'prepares' the parent class
00245 void Molecule::prepare() {
00246   get_new_frames(); // add a new frame if there are frames available
00247   DrawMolecule::prepare(); // do prepare for parent class
00248 }
00249 
00250 void Molecule::addForce(int theatom, const float *f) {
00251   force_indices.append(theatom);
00252   force_vectors.append3(&f[0]);
00253 }
00254 
00255 void Molecule::addPersistentForce(int theatom, const float *f) {
00256   // reset the force on this atom if any are stored
00257   // remove it completely if <f> is (0,0,0)
00258   
00259   float mag2 = f[0]*f[0] + f[1]*f[1] + f[2]*f[2];
00260   int ind = persistent_force_indices.find(theatom);
00261   if (ind < 0) {
00262     if (mag2 > 0) {
00263       // only set if non-zero
00264       reset_disp_list();
00265       persistent_force_indices.append(theatom);
00266       persistent_force_vectors.append3(&f[0]);
00267     }
00268   } else {
00269     if (mag2 > 0) {
00270       reset_disp_list();
00271       for (int i=0; i<3; i++) persistent_force_vectors[3L*ind+i] = f[i];
00272     } else {
00273       // remove the persistent force (a zero will be sent automatically!)
00274       persistent_force_indices.remove(ind);
00275 
00276       // remove same index three times since this is a ResizeArray 
00277       // and it will shift elements down as they are removed...
00278       persistent_force_vectors.remove(3L*ind);
00279       persistent_force_vectors.remove(3L*ind);
00280       persistent_force_vectors.remove(3L*ind);
00281     }
00282   }
00283 }
00284  

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