Пример #1
0
    void AngleBendContrib::getGrad(double *pos,double *grad) const {
      PRECONDITION(dp_forceField,"no owner");
      PRECONDITION(pos,"bad vector");
      PRECONDITION(grad,"bad vector");

      double dist[2] = {
        dp_forceField->distance(d_at1Idx, d_at2Idx, pos),
        dp_forceField->distance(d_at2Idx, d_at3Idx, pos)
      };

      RDGeom::Point3D p1(pos[3 * d_at1Idx],
        pos[3 * d_at1Idx + 1], pos[3 * d_at1Idx + 2]);
      RDGeom::Point3D p2(pos[3 * d_at2Idx],
        pos[3 * d_at2Idx + 1], pos[3 * d_at2Idx + 2]);
      RDGeom::Point3D p3(pos[3 * d_at3Idx],
        pos[3 * d_at3Idx + 1], pos[3 * d_at3Idx + 2]);
      double *g[3] = {
        &(grad[3 * d_at1Idx]),
        &(grad[3 * d_at2Idx]),
        &(grad[3 * d_at3Idx])
      };
      RDGeom::Point3D r[2] = {
        (p1 - p2) / dist[0],
        (p3 - p2) / dist[1]
      };
      double cosTheta = r[0].dotProduct(r[1]);
      double sinThetaSq = 1.0 - cosTheta * cosTheta;
      double sinTheta = std::max(((sinThetaSq > 0.0) ? sqrt(sinThetaSq) : 0.0), 1.0e-8);

      //std::cerr << "GRAD: " << cosTheta << " (" << acos(cosTheta)<< "), ";
      //std::cerr << sinTheta << " (" << asin(sinTheta)<< ")" << std::endl;
    
      // use the chain rule:
      // dE/dx = dE/dTheta * dTheta/dx

      // dE/dTheta is independent of cartesians:
      double dE_dTheta=getThetaDeriv(cosTheta,sinTheta);
    
      Utils::calcAngleBendGrad(r, dist, g, dE_dTheta, cosTheta, sinTheta);
    }
Пример #2
0
    void AngleBendContrib::getGrad(double *pos,double *grad) const {
      PRECONDITION(dp_forceField,"no owner");
      PRECONDITION(pos,"bad vector");
      PRECONDITION(grad,"bad vector");

      double dist1=this->dp_forceField->distance(this->d_at1Idx,this->d_at2Idx,pos);
      double dist2=this->dp_forceField->distance(this->d_at2Idx,this->d_at3Idx,pos);

      //std::cout << "\tAngle("<<this->d_at1Idx<<","<<this->d_at2Idx<<","<<this->d_at3Idx<<") " << dist1 << " " << dist2 << std::endl;
      
      RDGeom::Point3D p1(pos[3*this->d_at1Idx],
       pos[3*this->d_at1Idx+1],
       pos[3*this->d_at1Idx+2]);
      RDGeom::Point3D p2(pos[3*this->d_at2Idx],
       pos[3*this->d_at2Idx+1],
       pos[3*this->d_at2Idx+2]);
      RDGeom::Point3D p3(pos[3*this->d_at3Idx],
       pos[3*this->d_at3Idx+1],
       pos[3*this->d_at3Idx+2]);
      double *g1=&(grad[3*this->d_at1Idx]);
      double *g2=&(grad[3*this->d_at2Idx]);
      double *g3=&(grad[3*this->d_at3Idx]);

      RDGeom::Point3D p12=p1-p2;
      RDGeom::Point3D p32=p3-p2;
      double cosTheta = p12.dotProduct(p32)/(dist1*dist2);
      double sinTheta = std::max(sqrt(1.0-cosTheta*cosTheta),1e-8);

      //std::cerr << "GRAD: " << cosTheta << " (" << acos(cosTheta)<< "), ";
      //std::cerr << sinTheta << " (" << asin(sinTheta)<< ")" << std::endl;
    
      // use the chain rule:
      // dE/dx = dE/dTheta * dTheta/dx

      // dE/dTheta is independent of cartesians:
      double dE_dTheta=getThetaDeriv(cosTheta,sinTheta);
    
      // -------
      // dTheta/dx is trickier:
      double dCos_dS1=1./dist1 * (p32.x/dist2 - cosTheta*p12.x/dist1);
      double dCos_dS2=1./dist1 * (p32.y/dist2 - cosTheta*p12.y/dist1);
      double dCos_dS3=1./dist1 * (p32.z/dist2 - cosTheta*p12.z/dist1);

      double dCos_dS4=1./dist2 * (p12.x/dist1 - cosTheta*p32.x/dist2);
      double dCos_dS5=1./dist2 * (p12.y/dist1 - cosTheta*p32.y/dist2);
      double dCos_dS6=1./dist2 * (p12.z/dist1 - cosTheta*p32.z/dist2);

    
      g1[0] += dE_dTheta*dCos_dS1/(-sinTheta);
      g1[1] += dE_dTheta*dCos_dS2/(-sinTheta);
      g1[2] += dE_dTheta*dCos_dS3/(-sinTheta);

      g2[0] += dE_dTheta*(-dCos_dS1 - dCos_dS4)/(-sinTheta);
      g2[1] += dE_dTheta*(-dCos_dS2 - dCos_dS5)/(-sinTheta);
      g2[2] += dE_dTheta*(-dCos_dS3 - dCos_dS6)/(-sinTheta);
    
      g3[0] += dE_dTheta*dCos_dS4/(-sinTheta);
      g3[1] += dE_dTheta*dCos_dS5/(-sinTheta);
      g3[2] += dE_dTheta*dCos_dS6/(-sinTheta);

    }