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

FastPBC.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: FastPBC.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.6 $       $Date: 2022/03/17 20:21:42 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Fast PBC wrapping code
00019  ***************************************************************************/
00020 #include <stdio.h>
00021 #include <math.h>
00022 #include "Measure.h"
00023 #include "FastPBC.h"
00024 
00025 #ifdef VMDOPENACC
00026 #include <accelmath.h>
00027 #endif
00028 
00033 
00034 // If there is no CUDA defined, fall back to the CPU version.
00035 #ifndef VMDCUDA
00036 void fpbc_exec_unwrap(Molecule* mol, int first, int last, int sellen, int* indexlist) {
00037   fpbc_exec_unwrap_cpu(mol, first, last, sellen, indexlist);
00038 }
00039 
00040 void fpbc_exec_wrapatomic(Molecule* mol, int first, int last, int sellen, int* indexlist, 
00041   float* weights, AtomSel* csel, float* center) {
00042   fpbc_exec_wrapatomic_cpu(mol, first, last, sellen, indexlist, weights, csel, center);
00043 }
00044 
00045 void fpbc_exec_wrapcompound(Molecule* mol, int first, int last, int fnum, int *compoundmap, int sellen, int* indexlist,
00046   float* weights, AtomSel* csel, float* center, float* massarr) {
00047   fpbc_exec_wrapcompound_cpu(mol, first, last, fnum, compoundmap, sellen, indexlist, weights, csel, center, massarr);
00048 }
00049 
00050 void fpbc_exec_join(Molecule* mol, int first, int last, int fnum, int *compoundmap, int sellen, int* indexlist) {
00051   fpbc_exec_join_cpu(mol, first, last, fnum, compoundmap, sellen, indexlist);
00052 }
00053 
00054 void fpbc_exec_recenter(Molecule* mol, int first, int last, int csellen, int* cindexlist, int fnum, int *compoundmap, int sellen, int* indexlist, float* weights, AtomSel* csel, float* massarr) {
00055   fpbc_exec_recenter_cpu(mol, first, last, csellen, cindexlist, fnum, compoundmap, sellen, indexlist,  weights, csel, massarr);
00056 }
00057 #endif
00058 
00059 void fpbc_exec_wrapatomic_cpu(Molecule* mol, int first, int last, int sellen, int* indexlist, 
00060   float* weights, AtomSel* csel, float* center) {
00061   int f, i, j, k;
00062   float boxsize[3];
00063   float invboxsize[3];
00064   for (f=first; f<=last; f++) {
00065     Timestep *ts = mol->get_frame(f);
00066     boxsize[0] = ts->a_length;
00067     boxsize[1] = ts->b_length;
00068     boxsize[2] = ts->c_length;
00069     for (j=0; j < 3; j++) {
00070       invboxsize[j] = 1.0f/boxsize[j];
00071     }
00072     //If the center of mass needs to be found, find it! There is a function for that. :D
00073     if (csel != NULL) {
00074       measure_center(csel, ts->pos, weights, center);
00075     }
00076     for (k=0; k<sellen; k++) {
00077       i = indexlist[k];
00078       for (j=0; j < 3; j++) {
00079         //Compute the shift in terms of the number of box-lengths, scale by it, and reposition.
00080         ts->pos[i*3+j] = ts->pos[i*3+j] - (roundf((ts->pos[i*3+j] - center[j]) * invboxsize[j]) * boxsize[j]);
00081       }
00082     }
00083   }
00084 }
00085 
00086 
00087 void fpbc_exec_wrapcompound_cpu(Molecule* mol, int first, int last, int fnum, int *compoundmap, int sellen, int* indexlist,
00088   float* weights, AtomSel* csel, float* center, float* massarr) {
00089   int f, i, j, k, l;
00090   float boxsize[3];
00091   float invboxsize[3];
00092   for (f=first; f<=last; f++) {
00093     Timestep *ts = mol->get_frame(f);
00094     boxsize[0] = ts->a_length;
00095     boxsize[1] = ts->b_length;
00096     boxsize[2] = ts->c_length;
00097     for (j=0; j < 3; j++) {
00098       invboxsize[j] = 1.0f/boxsize[j];
00099     }
00100     //If the center of mass needs to be found, find it! There is a function for that. :D
00101     if (csel != NULL) {
00102       measure_center(csel, ts->pos, weights, center);
00103     }
00104     for (l = 0; l < fnum; l++) {
00105       int lowbound = compoundmap[l];
00106       int highbound = compoundmap[l+1];
00107       //calculate the mass weighted center of the compound
00108       float cmass = 0;            // initialize mass accumulator
00109       float ccenter[3] = {0,0,0}; // initialize position accumulator
00110       // cycle through atoms
00111       for (k = lowbound; k < highbound; k++ ) {
00112         i = indexlist[k];
00113         for (j=0; j < 3; j++) {
00114           ccenter[j] += massarr[i] * (ts->pos[i*3+j]);
00115         }
00116         cmass += massarr[i];
00117       }
00118       cmass = 1.0f / cmass;
00119       // divide pos by mass to get final mass weighted com
00120       for (j=0; j < 3; j++) {
00121         ccenter[j] *= cmass;
00122       }
00123       //move the compound
00124       for (k = lowbound; k < highbound; k++ ) {
00125         i = indexlist[k];
00126         for (j=0; j < 3; j++) {
00127           ts->pos[i*3+j] = ts->pos[i*3+j] - (roundf((ccenter[j] - center[j]) * invboxsize[j]) * boxsize[j]);
00128         }
00129       }
00130     }
00131   }
00132 }
00133 
00134 
00135 void fpbc_exec_join_cpu(Molecule* mol, int first, int last, int fnum, int *compoundmap, int sellen, int* indexlist) {
00136   int f, i, j, k, l;
00137   float boxsize[3];
00138   float invboxsize[3];
00139   float *pos;
00140   Timestep *ts;
00141   #pragma acc data copyin (indexlist[sellen], compoundmap[fnum+1])
00142   {
00143     //Loop over all the frames
00144     for (f=first; f<=last; f++) {
00145       //Grab the current coordinates and boxlength.
00146       ts = mol->get_frame(f);
00147       boxsize[0] = ts->a_length;
00148       boxsize[1] = ts->b_length;
00149       boxsize[2] = ts->c_length;
00150       pos = ts->pos;
00151       #pragma acc data copy(pos[3*mol->nAtoms]) copyin(boxsize[3]) create(invboxsize[3])  async(f%2)
00152       {
00153         #pragma acc kernels private(i, j, k, l) async(f%2)
00154         {
00155           //Minimize divisions by computing an inverse box-length.
00156           for (int q=0; q < 3; q++) {
00157             invboxsize[q] = 1.0f/boxsize[q];
00158           }
00159           #pragma acc loop independent private(i, j, k, l)
00160           for (l = 0; l < fnum; l++) {
00161             float ccenter[3];
00162             int lowbound = compoundmap[l];
00163             int highbound = compoundmap[l+1];
00164             i = indexlist[lowbound];
00165             //Use the first element within the compound as the center.
00166             for (j=0; j < 3; j++) {
00167               ccenter[j] = pos[(i+((highbound-lowbound)/2))*3+j];
00168             }
00169             //move the compound, wrapping it to be within half a box dimension from the center
00170             for (k = lowbound; k < highbound; k++ ) {
00171               i = indexlist[k];
00172               for (j=0; j < 3; j++) {
00173                 pos[i*3+j] = pos[i*3+j] - (rintf((pos[i*3+j] - ccenter[j]) * invboxsize[j]) * boxsize[j]);
00174               }
00175             }
00176           }
00177         }
00178       }
00179     }
00180     #pragma acc wait
00181   }
00182 }
00183 
00184 
00185 void fpbc_exec_unwrap_cpu(Molecule* mol, int first, int last, int sellen, int* indexlist) {
00186   Timestep *ts, *prev;
00187   int f, i, j, idx;
00188   float boxsize[3];
00189   float oldboxsize[3];
00190   float invboxsize[3];
00191   float *prevw = new float[3*sellen];//previous wrapped coordinates
00192   float curw; //holder for current wrapped coordinates
00193   float disp;//displacement holder
00194   
00195   //Setup previous wrapped coordinates for first go round.
00196   ts = mol->get_frame(first);
00197   for (i=0; i<sellen; i++) {
00198     for (j=0; j<3; j++) {
00199       prevw[3*i+j] = ts->pos[indexlist[i]*3+j];
00200     }
00201   }
00202   
00203   for (f=first+1; f<=last; f++) {
00204     ts = mol->get_frame(f);//current coordinates (wrapped)
00205     prev = mol->get_frame(f-1);//previous unwrapped coordinates
00206     boxsize[0] = ts->a_length;
00207     boxsize[1] = ts->b_length;
00208     boxsize[2] = ts->c_length;
00209     oldboxsize[0] = prev->a_length;
00210     oldboxsize[1] = prev->b_length;
00211     oldboxsize[2] = prev->c_length;
00212     for (j=0; j < 3; j++) {
00213       invboxsize[j] = 1.0f/boxsize[j];
00214     }
00215     for (i=0; i<sellen; i++) {
00216       idx = indexlist[i];
00217       for (j=0; j < 3; j++) {
00218         disp = ts->pos[idx*3+j] - prevw[3*i+j];
00219         curw = ts->pos[idx*3+j];
00220         ts->pos[idx*3+j] = prev->pos[idx*3+j] + disp
00221                                 -(floorf(disp * invboxsize[j] + 0.5f) * boxsize[j])
00222                                 -(floorf(((prevw[3*i+j]-prev->pos[idx*3+j])/oldboxsize[j])+0.5f)*(boxsize[j]-oldboxsize[j]));
00223         prevw[3*i+j] = curw;
00224       }
00225     }
00226   }
00227   delete [] prevw;
00228 }
00229 
00230 
00231 void fpbc_exec_recenter_cpu(Molecule* mol, int first, int last, int csellen, int* cindexlist, int fnum, int *compoundmap, int sellen, int* indexlist, float* weights, AtomSel* csel, float* massarr) {
00232   float center[3];//This needs to be passed, but since csel is guaranteed to point somewhere,
00233   //it does not need to be set.
00234   fpbc_exec_unwrap_cpu(mol, first, last, csellen, cindexlist);
00235   if (fnum)
00236     fpbc_exec_wrapcompound_cpu(mol, first, last, fnum, compoundmap, sellen, indexlist, weights, csel, &center[0], massarr);
00237   else
00238     fpbc_exec_wrapatomic_cpu(mol, first, last, sellen, indexlist, weights, csel, &center[0]);
00239 }
00240 
00241 
00242 
00243 

Generated on Fri Apr 19 02:44:23 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002