// calculate angle forces void calcAngleForces(AngleTerm angle) { if (LogLevel >= 1000) { FFlog.WriteLine("calcAngleForces for {0} - {1} - {2}", angle.Atom1, angle.Atom2, angle.Atom3); } Vector3 rb1 = position[angle.Atom1] - position[angle.Atom2]; Vector3 rb2 = position[angle.Atom3] - position[angle.Atom2]; float cosAlpha = (Vector3.Dot(rb1, rb2)) / (Vector3.Magnitude(rb1) * Vector3.Magnitude(rb2)); //float angleAlpha = Mathf.Acos(cosAlpha) * (180 / Mathf.PI); float mAlpha = angle.kAngle * (Mathf.Acos(cosAlpha) * (180.0f / Mathf.PI) - angle.Aeq); Vector3 fI = (mAlpha / (Vector3.Magnitude(rb1) * Mathf.Sqrt(1.0f - cosAlpha * cosAlpha))) * ((rb2 / Vector3.Magnitude(rb2)) - cosAlpha * (rb1 / Vector3.Magnitude(rb1))); Vector3 fK = (mAlpha / (Vector3.Magnitude(rb2) * Mathf.Sqrt(1.0f - cosAlpha * cosAlpha))) * ((rb1 / Vector3.Magnitude(rb1)) - cosAlpha * (rb2 / Vector3.Magnitude(rb2))); Vector3 fJ = -fI - fK; if (LogLevel >= 1000) { FFlog.WriteLine("angle: {0,12:f3} angle0: {1,12:f3} -- moment = {2,14:f5} ", Mathf.Acos(cosAlpha) * (180.0f / Mathf.PI), angle.Aeq, mAlpha); } if (LogLevel >= 10000) { FFlog.WriteLine(string.Format("force for atom {0,3}: ( {1,14:f6} ; {2,14:f6} ; {3,14:f6} )", angle.Atom1, fI.x, fI.y, fI.z)); FFlog.WriteLine(string.Format("force for atom {0,3}: ( {1,14:f6} ; {2,14:f6} ; {3,14:f6} )", angle.Atom2, fJ.x, fJ.y, fJ.z)); FFlog.WriteLine(string.Format("force for atom {0,3}: ( {1,14:f6} ; {2,14:f6} ; {3,14:f6} )", angle.Atom3, fK.x, fK.y, fK.z)); } forces[angle.Atom1] += fI; forces[angle.Atom2] += fJ; forces[angle.Atom3] += fK; if (LogLevel >= 10000) { FFlog.WriteLine("Updated forces:"); for (int iAtom = 0; iAtom < nAtoms; iAtom++) { FFlog.WriteLine(string.Format(" {0,4:d} - {1,5:d} {2,14:f6} {3,14:f6} {4,14:f6}", iAtom, atomList[iAtom], forces[iAtom].x, forces[iAtom].y, forces[iAtom].z)); } } }
void generateFF() { bondList.Clear(); angleList.Clear(); // set topology array bool[,] topo = new bool[nAtoms, nAtoms]; for (int iAtom = 0; iAtom < nAtoms; iAtom++) { for (int jAtom = 0; jAtom < nAtoms; jAtom++) { topo[iAtom, jAtom] = false; } } { int iAtom = 0; foreach (Atom At1 in GetComponent <GlobalCtrl>().list_curAtoms) { // cycle through connection points foreach (ConnectionStatus conPoint in At1.getAllConPoints()) { // get current atom index by comparison to entries in atomList int jAtom = -1; for (int kAtom = 0; kAtom < nAtoms; kAtom++) { if (atomList[kAtom] == conPoint.otherAtomID) { jAtom = kAtom; break; } } if (jAtom >= 0) { topo[iAtom, jAtom] = true; topo[jAtom, iAtom] = true; } } iAtom++; } } // now set all FF terms // pairwise terms, run over unique atom pairs for (int iAtom = 0; iAtom < nAtoms; iAtom++) { for (int jAtom = 0; jAtom < iAtom; jAtom++) { if (topo[iAtom, jAtom]) { BondTerm newBond = new BondTerm(); newBond.Atom1 = jAtom; newBond.Atom2 = iAtom; if (atomType[iAtom] == "C" && atomType[jAtom] == "C") { newBond.kBond = kbCC; newBond.Req = reqCC; } else if (atomType[iAtom] == "C" && atomType[jAtom] == "H" || atomType[iAtom] == "H" && atomType[jAtom] == "C") { newBond.kBond = kbCH; newBond.Req = reqCH; } // RENEW THIS LATER else if (atomType[iAtom] == "C" && atomType[jAtom] == "DUMMY" || atomType[iAtom] == "DUMMY" && atomType[jAtom] == "C") { newBond.kBond = kbCX; newBond.Req = reqCX; //newBond.kBond = kbCH; //newBond.Req = reqCH; } else if (atomType[iAtom] == "H" && atomType[jAtom] == "H") { newBond.kBond = kb; newBond.Req = reqHH; } else if (atomType[iAtom] == "H" && atomType[jAtom] == "DUMMY" || atomType[iAtom] == "DUMMY" && atomType[jAtom] == "H") { newBond.kBond = kbCX; newBond.Req = reqHX; //newBond.kBond = kb; //newBond.Req = reqHH; } else // take defaults for the time being { newBond.kBond = kb; newBond.Req = reqStd; } bondList.Add(newBond); } // else ... set here non-bonded interactions } } if (LogLevel >= 1000) { FFlog.WriteLine("Bond terms:"); FFlog.WriteLine(" Atom1 Atom2 kBond Req"); foreach (BondTerm bond in bondList) { FFlog.WriteLine(string.Format(" {0,4} - {1,4} {2,12:f3} {3,12:f3}", bond.Atom1, bond.Atom2, bond.kBond, bond.Req)); } } // angle terms // run over unique bond pairs foreach (BondTerm bond1 in bondList) { foreach (BondTerm bond2 in bondList) { // if we reached the same atom pair, we can skip if (bond1.Atom1 == bond2.Atom1 && bond1.Atom2 == bond2.Atom2) { break; } int idx = -1, jdx = -1, kdx = -1; if (bond1.Atom1 == bond2.Atom1) { idx = bond1.Atom2; jdx = bond1.Atom1; kdx = bond2.Atom2; } else if (bond1.Atom1 == bond2.Atom2) { idx = bond1.Atom2; jdx = bond1.Atom1; kdx = bond2.Atom1; } else if (bond1.Atom2 == bond2.Atom1) { idx = bond1.Atom1; jdx = bond1.Atom2; kdx = bond2.Atom2; } else if (bond1.Atom2 == bond2.Atom2) { idx = bond1.Atom1; jdx = bond1.Atom2; kdx = bond2.Atom1; } if (idx > -1) // if anything was found: set term { AngleTerm newAngle = new AngleTerm(); newAngle.Atom1 = kdx; // I put kdx->Atom1 and idx->Atom3 just for aesthetical reasons ;) newAngle.Atom2 = jdx; newAngle.Atom3 = idx; // currently only this angle type: newAngle.kAngle = ka; newAngle.Aeq = alphaNull; angleList.Add(newAngle); } } } if (LogLevel >= 1000) { FFlog.WriteLine("Angle terms:"); FFlog.WriteLine(" Atom1 Atom2 Atom3 kAngle Aeq"); foreach (AngleTerm angle in angleList) { FFlog.WriteLine(string.Format(" {0,4} - {1,4} - {2,4} {3,12:f3} {4,12:f3}", angle.Atom1, angle.Atom2, angle.Atom3, angle.kAngle, angle.Aeq)); } } }