void SimCalcs::stretchBond(int molIdx, int bondIdx, Real stretchDist) { Real* bondLengths = GPUCopy::bondLengthsPtr(); int bondStart = sb->moleculeData[MOL_BOND_START][molIdx]; int bondEnd = bondStart + sb->moleculeData[MOL_BOND_COUNT][molIdx]; int startIdx = sb->moleculeData[MOL_START][molIdx]; int molSize = sb->moleculeData[MOL_LEN][molIdx]; int end1 = (int)sb->bondData[BOND_A1_IDX][bondStart + bondIdx]; int end2 = (int)sb->bondData[BOND_A2_IDX][bondStart + bondIdx]; Real** aCoords = GPUCopy::atomCoordinatesPtr(); for (int i = 0; i < molSize; i++) { sb->unionFindParent[i] = i; } // Split the molecule atoms into two disjoint sets around the bond for (int i = bondStart; i < bondEnd; i++) { if (i == bondIdx + bondStart) continue; int a1 = (int)sb->bondData[BOND_A1_IDX][i] - startIdx; int a2 = (int)sb->bondData[BOND_A2_IDX][i] - startIdx; unionAtoms(a1, a2); } int side1 = find(end1 - startIdx); int side2 = find(end2 - startIdx); if (side1 == side2) { // std::cerr << "ERROR: EXPANDING BOND IN A RING!" << std::endl; return; } // Move each atom the appropriate distance for the bond stretch Real v[NUM_DIMENSIONS]; Real denon = 0.0; #pragma acc parallel loop deviceptr(aCoords) if (on_gpu) for (int i = 0; i < NUM_DIMENSIONS; i++) { v[i] = aCoords[i][end2] - aCoords[i][end1]; denon += v[i] * v[i]; } denon = sqrt(denon); for (int i = 0; i < NUM_DIMENSIONS; i++) { v[i] = v[i] / denon / 2.0; } for (int i = 0; i < molSize; i++) { if (find(i) == side2) { #pragma acc parallel loop deviceptr(aCoords) if (on_gpu) for (int j = 0; j < NUM_DIMENSIONS; j++) { aCoords[j][i + startIdx] += v[j] * stretchDist; } } else { #pragma acc parallel loop deviceptr(aCoords) if (on_gpu) for (int j = 0; j < NUM_DIMENSIONS; j++) { aCoords[j][i + startIdx] -= v[j] * stretchDist; } } } // Record the actual bond stretch #pragma acc parallel deviceptr(bondLengths) if (on_gpu) bondLengths[bondStart + bondIdx] += stretchDist; }
void SimBox::stretchBond(int molIdx, int bondIdx, Real stretchDist) { int bondStart = moleculeData[MOL_BOND_START][molIdx]; int bondEnd = bondStart + moleculeData[MOL_BOND_COUNT][molIdx]; changedBond = bondStart + bondIdx; prevBond = bondLengths[bondStart + bondIdx]; int startIdx = moleculeData[MOL_START][molIdx]; int molSize = moleculeData[MOL_LEN][molIdx]; int end1 = (int) bondData[BOND_A1_IDX][bondStart + bondIdx]; int end2 = (int) bondData[BOND_A2_IDX][bondStart + bondIdx]; for (int i = 0; i < molSize; i++) { unionFindParent[i] = i; } for (int i = bondStart; i < bondEnd; i++) { if (i == bondIdx + bondStart) continue; int a1 = (int) bondData[BOND_A1_IDX][i] - startIdx; int a2 = (int) bondData[BOND_A2_IDX][i] - startIdx; unionAtoms(a1, a2); } int side1 = find(end1 - startIdx); int side2 = find(end2 - startIdx); if (side1 == side2) { std::cout << "ERROR: EXPANDING BOND IN A RING!" << std::endl; return; } Real v[NUM_DIMENSIONS]; Real denon; for (int i = 0; i < NUM_DIMENSIONS; i++) { v[i] = atomCoordinates[i][side2] - atomCoordinates[i][side1]; denon += v[i] * v[i]; } denon = sqrt(denon); for (int i = 0; i < NUM_DIMENSIONS; i++) { v[i] = v[i] / denon / 2.0; } for (int i = 0; i < molSize; i++) { if(find(i) == side2) { for (int j = 0; j < NUM_DIMENSIONS; j++) { atomCoordinates[j][i + startIdx] += v[i]; } } else { for (int j = 0; j < NUM_DIMENSIONS; j++) { atomCoordinates[j][i + startIdx] -= v[i]; } } } bondLengths[bondStart + bondIdx] += stretchDist; }
void SimBox::expandAngle(int molIdx, int angleIdx, Real expandDeg) { int bondStart = moleculeData[MOL_BOND_START][molIdx]; int bondEnd = bondStart + moleculeData[MOL_BOND_COUNT][molIdx]; int angleStart = moleculeData[MOL_ANGLE_START][molIdx]; changedAngle = angleStart + angleIdx; prevAngle = angleSizes[angleStart + angleIdx]; int startIdx = moleculeData[MOL_START][molIdx]; int molSize = moleculeData[MOL_LEN][molIdx]; int end1 = (int) angleData[ANGLE_A1_IDX][angleStart + angleIdx]; int end2 = (int) angleData[ANGLE_A2_IDX][angleStart + angleIdx]; int mid = (int) angleData[ANGLE_MID_IDX][angleStart + angleIdx]; for (int i = 0; i < molSize; i++) { unionFindParent[i] = i; } for (int i = bondStart; i < bondEnd; i++) { int a1 = (int) bondData[BOND_A1_IDX][i]; int a2 = (int) bondData[BOND_A2_IDX][i]; if (a1 == mid || a2 == mid) continue; unionAtoms(a1 - startIdx, a2 - startIdx); } int group1 = find(end1 - startIdx); int group2 = find(end2 - startIdx); if (group1 == group2) { std::cout << "ERROR: EXPANDING ANGLE IN A RING!" << std::endl; return; } Real DEG2RAD = 3.14159256358979323846264 / 180.0; Real end1Mid[NUM_DIMENSIONS]; Real end2Mid[NUM_DIMENSIONS]; Real normal[NUM_DIMENSIONS]; Real mvector[NUM_DIMENSIONS]; for (int i = 0; i < NUM_DIMENSIONS; i++) { end1Mid[i] = atomCoordinates[i][mid] - atomCoordinates[i][end1]; end2Mid[i] = atomCoordinates[i][mid] - atomCoordinates[i][end2]; mvector[i] = atomCoordinates[i][mid]; } normal[0] = end1Mid[1] * end2Mid[2] - end2Mid[1] * end1Mid[2]; normal[1] = end2Mid[0] * end1Mid[2] - end1Mid[0] * end2Mid[2]; normal[2] = end1Mid[0] * end2Mid[1] - end2Mid[0] * end1Mid[1]; Real normLen = 0.0; for (int i = 0; i < NUM_DIMENSIONS; i++) { normLen += normal[i] * normal[i]; } normLen = sqrt(normLen); for (int i = 0; i < NUM_DIMENSIONS; i++) { normal[i] = normal[i] / normLen; } for (int i = startIdx; i < startIdx + molSize; i++) { Real theta; Real point[NUM_DIMENSIONS]; Real dot = 0.0; Real cross[NUM_DIMENSIONS]; if (find(i - startIdx) == group1) { theta = expandDeg * -DEG2RAD; } else if (find(i - startIdx) == group2) { theta = expandDeg * DEG2RAD; } else { continue; } for (int j = 0; j < NUM_DIMENSIONS; j++) { point[j] = atomCoordinates[j][i] - mvector[i]; dot += point[j] * normal[j]; } cross[0] = normal[1] * point[2] - point[1] * normal[2]; cross[1] = point[0] * normal[2] - normal[0] * point[2]; cross[2] = normal[0] * point[1] - point[0] * normal[1]; for (int j = 0; j < NUM_DIMENSIONS; j++) { point[j] = normal[j] * dot * (1 - cos(theta)) + point[j] * cos(theta) + cross[j] * sin(theta); atomCoordinates[j][i] = point[j] + mvector[j]; } } angleSizes[angleStart + angleIdx] += expandDeg; }
void SimCalcs::expandAngle(int molIdx, int angleIdx, Real expandDeg) { int** moleculeData = sb->moleculeData; Real* angleSizes = GPUCopy::angleSizesPtr(); int bondStart = moleculeData[MOL_BOND_START][molIdx]; int bondEnd = bondStart + moleculeData[MOL_BOND_COUNT][molIdx]; int angleStart = moleculeData[MOL_ANGLE_START][molIdx]; int startIdx = moleculeData[MOL_START][molIdx]; int molSize = moleculeData[MOL_LEN][molIdx]; int end1 = (int)sb->angleData[ANGLE_A1_IDX][angleStart + angleIdx]; int end2 = (int)sb->angleData[ANGLE_A2_IDX][angleStart + angleIdx]; int mid = (int)sb->angleData[ANGLE_MID_IDX][angleStart + angleIdx]; Real** aCoords = GPUCopy::atomCoordinatesPtr(); // Create a disjoint set of the atoms in the molecule for (int i = 0; i < molSize; i++) { sb->unionFindParent[i] = i; } // Union atoms connected by a bond for (int i = bondStart; i < bondEnd; i++) { int a1 = (int)sb->bondData[BOND_A1_IDX][i]; int a2 = (int)sb->bondData[BOND_A2_IDX][i]; if (a1 == mid || a2 == mid) continue; unionAtoms(a1 - startIdx, a2 - startIdx); } int group1 = find(end1 - startIdx); int group2 = find(end2 - startIdx); if (group1 == group2) { // std::cout << "ERROR: EXPANDING ANGLE IN A RING!" << std::endl; return; } Real DEG2RAD = 3.14159256358979323846264 / 180.0; Real end1Mid[NUM_DIMENSIONS]; Real end2Mid[NUM_DIMENSIONS]; Real normal[NUM_DIMENSIONS]; Real mvector[NUM_DIMENSIONS]; #pragma acc parallel loop deviceptr(aCoords) if (on_gpu) for (int i = 0; i < NUM_DIMENSIONS; i++) { end1Mid[i] = aCoords[i][mid] - aCoords[i][end1]; end2Mid[i] = aCoords[i][mid] - aCoords[i][end2]; mvector[i] = aCoords[i][mid]; } normal[0] = end1Mid[1] * end2Mid[2] - end2Mid[1] * end1Mid[2]; normal[1] = end2Mid[0] * end1Mid[2] - end1Mid[0] * end2Mid[2]; normal[2] = end1Mid[0] * end2Mid[1] - end2Mid[0] * end1Mid[1]; Real normLen = 0.0; for (int i = 0; i < NUM_DIMENSIONS; i++) { normLen += normal[i] * normal[i]; } normLen = sqrt(normLen); for (int i = 0; i < NUM_DIMENSIONS; i++) { normal[i] = normal[i] / normLen; } for (int i = startIdx; i < startIdx + molSize; i++) { Real theta; Real point[NUM_DIMENSIONS]; Real dot = 0.0; Real cross[NUM_DIMENSIONS]; if (find(i - startIdx) == group1) { theta = expandDeg * -DEG2RAD; } else if (find(i - startIdx) == group2) { theta = expandDeg * DEG2RAD; } else { continue; } #pragma acc parallel loop deviceptr(aCoords) if (on_gpu) for (int j = 0; j < NUM_DIMENSIONS; j++) { point[j] = aCoords[j][i] - mvector[j]; dot += point[j] * normal[j]; } cross[0] = normal[1] * point[2] - point[1] * normal[2]; cross[1] = point[0] * normal[2] - normal[0] * point[2]; cross[2] = normal[0] * point[1] - point[0] * normal[1]; #pragma acc parallel loop deviceptr(aCoords) if (on_gpu) for (int j = 0; j < NUM_DIMENSIONS; j++) { point[j] = (normal[j] * dot * (1 - cos(theta)) + point[j] * cos(theta) + cross[j] * sin(theta)); aCoords[j][i] = point[j] + mvector[j]; } } #pragma acc parallel deviceptr(angleSizes) if (on_gpu) angleSizes[angleStart + angleIdx] += expandDeg; }