Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

ComputeAniso.C

Go to the documentation of this file.
00001 
00007 #include "InfoStream.h"
00008 #include "ComputeAniso.h"
00009 #include "Molecule.h"
00010 #include "Parameters.h"
00011 #include "Node.h"
00012 #include "ReductionMgr.h"
00013 #include "Lattice.h"
00014 #include "PressureProfile.h"
00015 #include "Debug.h"
00016 
00017 #define CALCULATE_ANISO
00018 
00019 // static initialization
00020 int AnisoElem::pressureProfileSlabs = 0;
00021 int AnisoElem::pressureProfileAtomTypes = 1;
00022 BigReal AnisoElem::pressureProfileThickness = 0;
00023 BigReal AnisoElem::pressureProfileMin = 0;
00024 
00025 void AnisoElem::getMoleculePointers
00026     (Molecule* mol, int* count, int32*** byatom, Aniso** structarray)
00027 {
00028 #ifdef MEM_OPT_VERSION
00029   NAMD_die("Should not be called in AnisoElem::getMoleculePointers in memory optimized version!");
00030 #else
00031   *count = mol->numAnisos;
00032   *byatom = mol->anisosByAtom;
00033   *structarray = mol->anisos;
00034 #endif
00035 }
00036 
00037 void AnisoElem::getParameterPointers(Parameters *p, const AnisoValue **v) {
00038   *v = NULL;  // parameters are stored in the structure
00039 }
00040 
00041 void AnisoElem::computeForce(BigReal *reduction, 
00042                                 BigReal *pressureProfileData)
00043 {
00044   DebugM(3, "::computeForce() localIndex = " << localIndex[0] << " "
00045                << localIndex[1] << " " << localIndex[2] << " "
00046                << localIndex[3] << std::endl);
00047 
00048 #ifdef CALCULATE_ANISO
00049   // used some comments from Ed Harder's implementation in CHARMM
00050 
00051   const BigReal kpar0  = 2*value->k11;  // force constants
00052   const BigReal kperp0 = 2*value->k22;
00053   const BigReal kiso0  = 2*value->k33;
00054 
00055   const Position & ri = p[0]->x[localIndex[0]].position;    // atom I
00056   const Position & rj = p[0]->x[localIndex[0]+1].position;  // atom I's Drude
00057   const Position & rl = p[1]->x[localIndex[1]].position;    // atom L
00058   const Position & rm = p[2]->x[localIndex[2]].position;    // atom M
00059   const Position & rn = p[3]->x[localIndex[3]].position;    // atom N
00060 
00061   // calculate parallel and perpendicular displacement vectors
00062   const Lattice & lattice = p[0]->p->lattice;
00063   Vector r_il = lattice.delta(ri,rl);  // shortest vector image:  ri - rl
00064   Vector r_mn = lattice.delta(rm,rn);  // shortest vector image:  rm - rn
00065 
00066   BigReal r_il_invlen = r_il.rlength();  // need recip lengths of r_il, r_mn
00067   BigReal r_mn_invlen = r_mn.rlength();
00068 
00069   Vector u1 = r_il * r_il_invlen;  // normalize r_il, r_mn
00070   Vector u2 = r_mn * r_mn_invlen;
00071 
00072   Vector dr = rj - ri;  // Drude displacement vector (ri, rj are in same patch)
00073 
00074   BigReal dpar  = dr * u1;  // parallel displacement
00075   BigReal dperp = dr * u2;  // perpendicular displacement
00076 
00077   // aniso spring energy
00078   // kpar reduces response along carbonyl vector
00079   // kperp reduces response perp to bond vector
00080   //   (reg in and out of plane response)
00081   BigReal eaniso;
00082   eaniso = 0.5*kpar0*dpar*dpar + 0.5*kperp0*dperp*dperp + 0.5*kiso0*(dr*dr);
00083 
00084   // calculate force vectors in one direction only:
00085   // fi = -(fj + fl),  fn = -fm
00086 
00087   // force on atom j
00088   Vector fj = -kiso0 * dr;
00089   fj -= kpar0 * dpar * u1;
00090   fj -= kperp0 * dperp * u2;
00091 
00092   // force on atom l
00093   Vector fl = kpar0 * dpar * r_il_invlen * dr;
00094   fl -= kpar0 * dpar * dpar * r_il_invlen * u1;
00095 
00096   // force on atom m
00097   Vector fm = kperp0 * dperp * dperp * r_mn_invlen * u2;
00098   fm -= kperp0 * dperp * r_mn_invlen * dr;
00099 
00100   // accumulate forces
00101   p[0]->f[localIndex[0]] -= (fj + fl);
00102   p[0]->f[localIndex[0]+1] += fj;
00103   p[1]->f[localIndex[1]] += fl;
00104   p[2]->f[localIndex[2]] += fm;
00105   p[3]->f[localIndex[3]] -= fm;
00106 
00107   // update potential
00108   reduction[anisoEnergyIndex] += eaniso;
00109 
00110   // update virial
00111   reduction[virialIndex_XX] += fj.x * dr.x - fl.x * r_il.x + fm.x * r_mn.x;
00112   reduction[virialIndex_XY] += fj.x * dr.y - fl.x * r_il.y + fm.x * r_mn.y;
00113   reduction[virialIndex_XZ] += fj.x * dr.z - fl.x * r_il.z + fm.x * r_mn.z;
00114   reduction[virialIndex_YX] += fj.y * dr.x - fl.y * r_il.x + fm.y * r_mn.x;
00115   reduction[virialIndex_YY] += fj.y * dr.y - fl.y * r_il.y + fm.y * r_mn.y;
00116   reduction[virialIndex_YZ] += fj.y * dr.z - fl.y * r_il.z + fm.y * r_mn.z;
00117   reduction[virialIndex_ZX] += fj.z * dr.x - fl.z * r_il.x + fm.z * r_mn.x;
00118   reduction[virialIndex_ZY] += fj.z * dr.y - fl.z * r_il.y + fm.z * r_mn.y;
00119   reduction[virialIndex_ZZ] += fj.z * dr.z - fl.z * r_il.z + fm.z * r_mn.z;
00120 
00121   // update pressure profile data
00122   if (pressureProfileData) {
00123     BigReal zi = p[0]->x[localIndex[0]].position.z;
00124     BigReal zj = p[0]->x[localIndex[0]+1].position.z;
00125     BigReal zl = p[1]->x[localIndex[1]].position.z;
00126     BigReal zm = p[2]->x[localIndex[2]].position.z;
00127     BigReal zn = p[3]->x[localIndex[3]].position.z;
00128     int ni = (int)floor((zi-pressureProfileMin)/pressureProfileThickness);
00129     int nj = (int)floor((zj-pressureProfileMin)/pressureProfileThickness);
00130     int nl = (int)floor((zl-pressureProfileMin)/pressureProfileThickness);
00131     int nm = (int)floor((zm-pressureProfileMin)/pressureProfileThickness);
00132     int nn = (int)floor((zn-pressureProfileMin)/pressureProfileThickness);
00133     pp_clamp(ni, pressureProfileSlabs);
00134     pp_clamp(nj, pressureProfileSlabs);
00135     pp_clamp(nl, pressureProfileSlabs);
00136     pp_clamp(nm, pressureProfileSlabs);
00137     pp_clamp(nn, pressureProfileSlabs);
00138     int pi = p[0]->x[localIndex[0]].partition;
00139     int pj = p[0]->x[localIndex[0]+1].partition;
00140     int pl = p[1]->x[localIndex[1]].partition;
00141     int pm = p[2]->x[localIndex[2]].partition;
00142     int pn = p[3]->x[localIndex[3]].partition;
00143     int pt = pressureProfileAtomTypes;
00144     pp_reduction(pressureProfileSlabs, nj, ni,
00145         pj, pi, pt, fj.x * dr.x, fj.y * dr.y, fj.z * dr.z,
00146         pressureProfileData);
00147     pp_reduction(pressureProfileSlabs, ni, nl,
00148         pi, pl, pt, -fl.x * r_il.x, -fl.y * r_il.y, -fl.z * r_il.z,
00149         pressureProfileData);
00150     pp_reduction(pressureProfileSlabs, nm, nn,
00151         pm, pn, pt, fm.x * r_mn.x, fm.y * r_mn.y, fm.z * r_mn.z,
00152         pressureProfileData);
00153   }
00154 #endif
00155 }
00156 
00157 
00158 void AnisoElem::submitReductionData(BigReal *data, SubmitReduction *reduction)
00159 {
00160   reduction->item(REDUCTION_BOND_ENERGY) += data[anisoEnergyIndex];
00161   ADD_TENSOR(reduction,REDUCTION_VIRIAL_NORMAL,data,virialIndex);
00162 }
00163 

Generated on Fri May 25 04:07:14 2012 for NAMD by  doxygen 1.3.9.1