00001
00007 #include "InfoStream.h"
00008 #include "ComputeDihedrals.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
00018
00019 int DihedralElem::pressureProfileSlabs = 0;
00020 int DihedralElem::pressureProfileAtomTypes = 1;
00021 BigReal DihedralElem::pressureProfileThickness = 0;
00022 BigReal DihedralElem::pressureProfileMin = 0;
00023
00024 void DihedralElem::getMoleculePointers
00025 (Molecule* mol, int* count, int32*** byatom, Dihedral** structarray)
00026 {
00027 #ifdef MEM_OPT_VERSION
00028 NAMD_die("Should not be called in DihedralElem::getMoleculePointers in memory optimized version!");
00029 #else
00030 *count = mol->numDihedrals;
00031 *byatom = mol->dihedralsByAtom;
00032 *structarray = mol->dihedrals;
00033 #endif
00034 }
00035
00036 void DihedralElem::getParameterPointers(Parameters *p, const DihedralValue **v) {
00037 *v = p->dihedral_array;
00038 }
00039
00040 void DihedralElem::computeForce(BigReal *reduction,
00041 BigReal *pressureProfileData)
00042 {
00043 DebugM(3, "::computeForce() localIndex = " << localIndex[0] << " "
00044 << localIndex[1] << " " << localIndex[2] << std::endl);
00045
00046
00047 const Position & pos0 = p[0]->x[localIndex[0]].position;
00048 const Lattice & lattice = p[0]->p->lattice;
00049 const Position & pos1 = p[1]->x[localIndex[1]].position;
00050 const Vector r12 = lattice.delta(pos0,pos1);
00051 const Position & pos2 = p[2]->x[localIndex[2]].position;
00052 const Vector r23 = lattice.delta(pos1,pos2);
00053 const Position & pos3 = p[3]->x[localIndex[3]].position;
00054 const Vector r34 = lattice.delta(pos2,pos3);
00055
00056
00057 Vector A = cross(r12,r23);
00058 register BigReal rAinv = A.rlength();
00059 Vector B = cross(r23,r34);
00060 register BigReal rBinv = B.rlength();
00061 Vector C = cross(r23,A);
00062 register BigReal rCinv = C.rlength();
00063
00064
00065 BigReal cos_phi = (A*B)*(rAinv*rBinv);
00066 BigReal sin_phi = (C*B)*(rCinv*rBinv);
00067
00068 BigReal phi= -atan2(sin_phi,cos_phi);
00069
00070 BigReal K=0;
00071 BigReal K1=0;
00072
00073
00074 int multiplicity = value->multiplicity;
00075
00076
00077
00078
00079 for (int mult_num=0; mult_num<multiplicity; mult_num++)
00080 {
00081
00082 Real k = value->values[mult_num].k * scale;
00083 Real delta = value->values[mult_num].delta;
00084 int n = value->values[mult_num].n;
00085
00086
00087 if (n)
00088 {
00089
00090 K += k*(1+cos(n*phi - delta));
00091 K1 += -n*k*sin(n*phi - delta);
00092 }
00093 else
00094 {
00095
00096 BigReal diff = phi-delta;
00097 if (diff < -PI) diff += TWOPI;
00098 else if (diff > PI) diff -= TWOPI;
00099
00100 K += k*diff*diff;
00101 K1 += 2.0*k*diff;
00102 }
00103 }
00104
00105 Force f1,f2,f3;
00106
00107
00108
00109 B *= rBinv;
00110
00111
00112
00113
00114
00115 if (fabs(sin_phi) > 0.1)
00116 {
00117
00118
00119
00120 A *= rAinv;
00121 Vector dcosdA;
00122 Vector dcosdB;
00123
00124 dcosdA.x = rAinv*(cos_phi*A.x-B.x);
00125 dcosdA.y = rAinv*(cos_phi*A.y-B.y);
00126 dcosdA.z = rAinv*(cos_phi*A.z-B.z);
00127
00128 dcosdB.x = rBinv*(cos_phi*B.x-A.x);
00129 dcosdB.y = rBinv*(cos_phi*B.y-A.y);
00130 dcosdB.z = rBinv*(cos_phi*B.z-A.z);
00131
00132 K1 = K1/sin_phi;
00133
00134 f1.x = K1*(r23.y*dcosdA.z - r23.z*dcosdA.y);
00135 f1.y = K1*(r23.z*dcosdA.x - r23.x*dcosdA.z);
00136 f1.z = K1*(r23.x*dcosdA.y - r23.y*dcosdA.x);
00137
00138 f3.x = K1*(r23.z*dcosdB.y - r23.y*dcosdB.z);
00139 f3.y = K1*(r23.x*dcosdB.z - r23.z*dcosdB.x);
00140 f3.z = K1*(r23.y*dcosdB.x - r23.x*dcosdB.y);
00141
00142 f2.x = K1*(r12.z*dcosdA.y - r12.y*dcosdA.z
00143 + r34.y*dcosdB.z - r34.z*dcosdB.y);
00144 f2.y = K1*(r12.x*dcosdA.z - r12.z*dcosdA.x
00145 + r34.z*dcosdB.x - r34.x*dcosdB.z);
00146 f2.z = K1*(r12.y*dcosdA.x - r12.x*dcosdA.y
00147 + r34.x*dcosdB.y - r34.y*dcosdB.x);
00148 }
00149 else
00150 {
00151
00152
00153
00154
00155
00156 C *= rCinv;
00157
00158 Vector dsindC;
00159 Vector dsindB;
00160
00161 dsindC.x = rCinv*(sin_phi*C.x-B.x);
00162 dsindC.y = rCinv*(sin_phi*C.y-B.y);
00163 dsindC.z = rCinv*(sin_phi*C.z-B.z);
00164
00165 dsindB.x = rBinv*(sin_phi*B.x-C.x);
00166 dsindB.y = rBinv*(sin_phi*B.y-C.y);
00167 dsindB.z = rBinv*(sin_phi*B.z-C.z);
00168
00169 K1 = -K1/cos_phi;
00170
00171 f1.x = K1*((r23.y*r23.y + r23.z*r23.z)*dsindC.x
00172 - r23.x*r23.y*dsindC.y
00173 - r23.x*r23.z*dsindC.z);
00174 f1.y = K1*((r23.z*r23.z + r23.x*r23.x)*dsindC.y
00175 - r23.y*r23.z*dsindC.z
00176 - r23.y*r23.x*dsindC.x);
00177 f1.z = K1*((r23.x*r23.x + r23.y*r23.y)*dsindC.z
00178 - r23.z*r23.x*dsindC.x
00179 - r23.z*r23.y*dsindC.y);
00180
00181 f3 = cross(K1,dsindB,r23);
00182
00183 f2.x = K1*(-(r23.y*r12.y + r23.z*r12.z)*dsindC.x
00184 +(2.0*r23.x*r12.y - r12.x*r23.y)*dsindC.y
00185 +(2.0*r23.x*r12.z - r12.x*r23.z)*dsindC.z
00186 +dsindB.z*r34.y - dsindB.y*r34.z);
00187 f2.y = K1*(-(r23.z*r12.z + r23.x*r12.x)*dsindC.y
00188 +(2.0*r23.y*r12.z - r12.y*r23.z)*dsindC.z
00189 +(2.0*r23.y*r12.x - r12.y*r23.x)*dsindC.x
00190 +dsindB.x*r34.z - dsindB.z*r34.x);
00191 f2.z = K1*(-(r23.x*r12.x + r23.y*r12.y)*dsindC.z
00192 +(2.0*r23.z*r12.x - r12.z*r23.x)*dsindC.x
00193 +(2.0*r23.z*r12.y - r12.z*r23.y)*dsindC.y
00194 +dsindB.y*r34.x - dsindB.x*r34.y);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 p[0]->f[localIndex[0]].x += f1.x;
00204 p[0]->f[localIndex[0]].y += f1.y;
00205 p[0]->f[localIndex[0]].z += f1.z;
00206
00207 p[1]->f[localIndex[1]].x += f2.x - f1.x;
00208 p[1]->f[localIndex[1]].y += f2.y - f1.y;
00209 p[1]->f[localIndex[1]].z += f2.z - f1.z;
00210
00211 p[2]->f[localIndex[2]].x += f3.x - f2.x;
00212 p[2]->f[localIndex[2]].y += f3.y - f2.y;
00213 p[2]->f[localIndex[2]].z += f3.z - f2.z;
00214
00215 p[3]->f[localIndex[3]].x += -f3.x;
00216 p[3]->f[localIndex[3]].y += -f3.y;
00217 p[3]->f[localIndex[3]].z += -f3.z;
00218
00219
00220 if ( p[0]->af ) {
00221 p[0]->af[localIndex[0]].x += f1.x;
00222 p[0]->af[localIndex[0]].y += f1.y;
00223 p[0]->af[localIndex[0]].z += f1.z;
00224
00225 p[1]->af[localIndex[1]].x += f2.x - f1.x;
00226 p[1]->af[localIndex[1]].y += f2.y - f1.y;
00227 p[1]->af[localIndex[1]].z += f2.z - f1.z;
00228
00229 p[2]->af[localIndex[2]].x += f3.x - f2.x;
00230 p[2]->af[localIndex[2]].y += f3.y - f2.y;
00231 p[2]->af[localIndex[2]].z += f3.z - f2.z;
00232
00233 p[3]->af[localIndex[3]].x += -f3.x;
00234 p[3]->af[localIndex[3]].y += -f3.y;
00235 p[3]->af[localIndex[3]].z += -f3.z;
00236 }
00237
00238 DebugM(3, "::computeForce() -- ending with delta energy " << K << std::endl);
00239 reduction[dihedralEnergyIndex] += K;
00240 reduction[virialIndex_XX] += ( f1.x * r12.x + f2.x * r23.x + f3.x * r34.x );
00241 reduction[virialIndex_XY] += ( f1.x * r12.y + f2.x * r23.y + f3.x * r34.y );
00242 reduction[virialIndex_XZ] += ( f1.x * r12.z + f2.x * r23.z + f3.x * r34.z );
00243 reduction[virialIndex_YX] += ( f1.y * r12.x + f2.y * r23.x + f3.y * r34.x );
00244 reduction[virialIndex_YY] += ( f1.y * r12.y + f2.y * r23.y + f3.y * r34.y );
00245 reduction[virialIndex_YZ] += ( f1.y * r12.z + f2.y * r23.z + f3.y * r34.z );
00246 reduction[virialIndex_ZX] += ( f1.z * r12.x + f2.z * r23.x + f3.z * r34.x );
00247 reduction[virialIndex_ZY] += ( f1.z * r12.y + f2.z * r23.y + f3.z * r34.y );
00248 reduction[virialIndex_ZZ] += ( f1.z * r12.z + f2.z * r23.z + f3.z * r34.z );
00249
00250 if (pressureProfileData) {
00251 BigReal z1 = p[0]->x[localIndex[0]].position.z;
00252 BigReal z2 = p[1]->x[localIndex[1]].position.z;
00253 BigReal z3 = p[2]->x[localIndex[2]].position.z;
00254 BigReal z4 = p[3]->x[localIndex[3]].position.z;
00255 int n1 = (int)floor((z1-pressureProfileMin)/pressureProfileThickness);
00256 int n2 = (int)floor((z2-pressureProfileMin)/pressureProfileThickness);
00257 int n3 = (int)floor((z3-pressureProfileMin)/pressureProfileThickness);
00258 int n4 = (int)floor((z4-pressureProfileMin)/pressureProfileThickness);
00259 pp_clamp(n1, pressureProfileSlabs);
00260 pp_clamp(n2, pressureProfileSlabs);
00261 pp_clamp(n3, pressureProfileSlabs);
00262 pp_clamp(n4, pressureProfileSlabs);
00263 int p1 = p[0]->x[localIndex[0]].partition;
00264 int p2 = p[1]->x[localIndex[1]].partition;
00265 int p3 = p[2]->x[localIndex[2]].partition;
00266 int p4 = p[3]->x[localIndex[3]].partition;
00267 int pn = pressureProfileAtomTypes;
00268 pp_reduction(pressureProfileSlabs, n1, n2,
00269 p1, p2, pn,
00270 f1.x * r12.x, f1.y * r12.y, f1.z * r12.z,
00271 pressureProfileData);
00272 pp_reduction(pressureProfileSlabs, n2, n3,
00273 p2, p3, pn,
00274 f2.x * r23.x, f2.y * r23.y, f2.z * r23.z,
00275 pressureProfileData);
00276 pp_reduction(pressureProfileSlabs, n3, n4,
00277 p3, p4, pn,
00278 f3.x * r34.x, f3.y * r34.y, f3.z * r34.z,
00279 pressureProfileData);
00280 }
00281 }
00282
00283
00284 void DihedralElem::submitReductionData(BigReal *data, SubmitReduction *reduction)
00285 {
00286 reduction->item(REDUCTION_DIHEDRAL_ENERGY) += data[dihedralEnergyIndex];
00287 ADD_TENSOR(reduction,REDUCTION_VIRIAL_NORMAL,data,virialIndex);
00288 ADD_TENSOR(reduction,REDUCTION_VIRIAL_AMD_DIHE,data,virialIndex);
00289 }
00290