Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}