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