Esempio n. 1
0
double ContactMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
  Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
  double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc );

  if( !doNotCalculateDerivatives() ) {
    Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
    double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc );
    addAtomDerivatives( 1, 0, (-dfunc)*distance, myatoms );
    addAtomDerivatives( 1, 1, (+dfunc)*distance, myatoms );
    myatoms.addBoxDerivatives( 1, (-dfunc)*Tensor(distance,distance) );
  }
  return sw;
}
double ContactAlignedMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
  double f_dot, dot_df; 

  std::vector<double> orient0(ncomp), orient1(ncomp);
  getOrientationVector( myatoms.getIndex(0), true, orient0 );
  getOrientationVector( myatoms.getIndex(1), true, orient1 );
  double dot=0; for(unsigned k=2;k<orient0.size();++k) dot+=orient0[k]*orient1[k];
  f_dot=0.5*( 1 + dot ); dot_df=0.5; 

  // Retrieve the weight of the connection
  double weight = myatoms.getValue(0); myatoms.setValue(0,1.0); 

  if( !doNotCalculateDerivatives() ){
      Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
      double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( distance.modulo(), dfunc );
      addAtomDerivatives( 1, 0, (-dfunc)*f_dot*distance, myatoms );
      addAtomDerivatives( 1, 1, (+dfunc)*f_dot*distance, myatoms ); 
      myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) ); 

      // Add derivatives of orientation 
      for(unsigned k=2;k<orient0.size();++k){ orient0[k]*=sw*dot_df; orient1[k]*=sw*dot_df; }
      addOrientationDerivatives( 1, 0, orient1, myatoms );
      addOrientationDerivatives( 1, 1, orient0, myatoms );
  }
  return weight*f_dot;
}
double InterMolecularTorsions::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
  Vector v1, v2, dv1, dv2, dconn, conn = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );

  // Retrieve vectors
  std::vector<double> orient0( 5 ), orient1( 5 );
  getInputData( 0, true, myatoms, orient0 );
  getInputData( 1, true, myatoms, orient1 );
  for(unsigned i=0; i<3; ++i) { v1[i]=orient0[2+i]; v2[i]=orient1[2+i]; }
  if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0;

  // Evaluate angle
  Torsion t; double angle = t.compute( v1, conn, v2, dv1, dconn, dv2 );
  for(unsigned i=0; i<3; ++i) { orient0[i+2]=dv1[i]; orient1[i+2]=dv2[i]; }

  // And accumulate derivatives
  if( !doNotCalculateDerivatives() ) {
    MultiValue& myder0=getInputDerivatives( 0, true, myatoms );
    mergeInputDerivatives( 1, 2, orient1.size(), 0, orient0, myder0, myatoms );
    MultiValue& myder1=getInputDerivatives( 1, true, myatoms );
    mergeInputDerivatives( 1, 2, orient0.size(), 1, orient1, myder1, myatoms );
    addAtomDerivatives( 1, 0, -dconn, myatoms ); addAtomDerivatives( 1, 1, dconn, myatoms );
    myatoms.addBoxDerivatives( 1, -extProduct( conn, dconn ) );
  }

  return angle;
}
Esempio n. 4
0
void ClusterWithSurface::retrieveAtomsInCluster( const unsigned& clust, std::vector<unsigned>& myatoms ) const {
  std::vector<unsigned> tmpat; myclusters->retrieveAtomsInCluster( clust, tmpat );

  // Prevent double counting
  std::vector<bool> incluster( getNumberOfNodes(), false );
  for(unsigned i=0;i<tmpat.size();++i) incluster[tmpat[i]]=true;

  // Find the atoms in the the clusters
  std::vector<bool> surface_atom( getNumberOfNodes(), false ); 
  for(unsigned i=0;i<tmpat.size();++i){
      for(unsigned j=0;j<getNumberOfNodes();++j){
         if( incluster[j] ) continue;
         double dist2=getSeparation( getPosition(tmpat[i]), getPosition(j) ).modulo2();
         if( dist2<rcut_surf2 ){ surface_atom[j]=true; }
      }
  }
  unsigned nsurf_at=0; 
  for(unsigned j=0;j<getNumberOfNodes();++j){
     if( surface_atom[j] ) nsurf_at++; 
  }
  myatoms.resize( nsurf_at + tmpat.size() );
  for(unsigned i=0;i<tmpat.size();++i) myatoms[i]=tmpat[i];
  unsigned nn=tmpat.size();
  for(unsigned j=0;j<getNumberOfNodes();++j){
      if( surface_atom[j] ){ myatoms[nn]=j; nn++; }
  }
  plumed_assert( nn==myatoms.size() );
}
Esempio n. 5
0
double DistanceFromContour::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
  Vector distance = getSeparation( getPosition(getNumberOfAtoms()-1), myatoms.getPosition(0) );
  std::vector<double> pp(3), der(3,0); for(unsigned j=0;j<3;++j) pp[j] = distance[j]; 

  // Now create the kernel and evaluate
  KernelFunctions kernel( pp, bw, kerneltype, false, 1.0, true );
  double newval = kernel.evaluate( pval, der, true );

  if( mybasemulticolvars[0]->isDensity() ){ 
      if( !doNotCalculateDerivatives() && derivTime ){
          MultiValue& myvals=myatoms.getUnderlyingMultiValue();
          Vector vder; unsigned basen=myvals.getNumberOfDerivatives() - 12;
          for(unsigned i=0;i<3;++i){ 
              vder[i]=der[i]; myvals.addDerivative( 1, basen+i, vder[i] ); 
          }
          myatoms.setValue( 2, der[dir] );
          addAtomDerivatives( 1, 0, -vder, myatoms );
          myatoms.addBoxDerivatives( 1, Tensor(vder,distance) );
      }
      myatoms.setValue( 0, 1.0 ); return newval; 
  }

  // This does the stuff for averaging
  myatoms.setValue( 0, newval );

  // This gets the average if we are using a phase field
  std::vector<double> cvals( mybasemulticolvars[0]->getNumberOfQuantities() );
  mybasedata[0]->retrieveValueWithIndex( tindex, false, cvals );
  return newval*cvals[0]*cvals[1]; 
}
Esempio n. 6
0
double OrientationSphere::compute(){
   // Make sure derivatives for central atom are only calculated once
   VectorMultiColvar* vv = dynamic_cast<VectorMultiColvar*>( getBaseMultiColvar(0) );
   vv->firstcall=true;

   weightHasDerivatives=true;   // The weight has no derivatives really
   double sw, value=0, denom=0, dot, f_dot, dot_df, dfunc; Vector distance;

   getVectorForBaseTask(0, catom_orient );
   for(unsigned i=1;i<getNAtoms();++i){
      distance=getSeparation( getPositionOfCentralAtom(0), getPositionOfCentralAtom(i) );
      sw = switchingFunction.calculateSqr( distance.modulo2(), dfunc );
      if( sw>=getTolerance() ){    
         getVectorForBaseTask( i, this_orient );
         // Calculate the dot product wrt to this position 
         dot=0; for(unsigned k=0;k<catom_orient.size();++k) dot+=catom_orient[k]*this_orient[k];  
         f_dot = transformDotProduct( dot, dot_df ); 
         // N.B. We are assuming here that the imaginary part of the dot product is zero
         for(unsigned k=0;k<catom_orient.size();++k){
            this_orient[k]*=sw*dot_df; catom_der[k]=sw*dot_df*catom_orient[k];
         }  

         // Set the derivatives wrt of the numerator
         addOrientationDerivatives( 0, this_orient ); 
         addOrientationDerivatives( i, catom_der );  
         addCentralAtomsDerivatives( 0, 0, f_dot*(-dfunc)*distance );
         addCentralAtomsDerivatives( i, 0, f_dot*(dfunc)*distance );
         addBoxDerivatives( f_dot*(-dfunc)*Tensor(distance,distance) );
         value += sw*f_dot;
         // Set the derivatives wrt to the numerator
         addCentralAtomsDerivatives( 0, 1, (-dfunc)*distance );
         addCentralAtomsDerivatives( i, 1, (dfunc)*distance );
         addBoxDerivativesOfWeight( (-dfunc)*Tensor(distance,distance) );
         denom += sw;
      }
   }
   
   // Now divide everything
   unsigned nder = getNumberOfDerivatives();
   for(unsigned i=0;i<nder;++i){
      setElementDerivative( i, getElementDerivative(i)/denom - (value*getElementDerivative(nder+i))/(denom*denom) );  
      setElementDerivative( nder + i, 0.0 );
   }
   weightHasDerivatives=false;   // Weight has no derivatives we just use the holder for weight to store some stuff
   return value / denom;
}
Esempio n. 7
0
double TopologyMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const {
  HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( kerneltype );

  // Initialise to zero density on all bins
  for(unsigned bin=0; bin<maxbins; ++bin) myatoms.setValue(bin+1,0);
  // Calculate whether or not atoms 1 and 2 are within cutoff (can use delta here as pbc are done in atom setup)
  Vector d1 = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double d1_len = d1.modulo();
  d1 = d1 / d1_len;  // Convert vector into director
  AtomNumber a1 = myatoms.getAbsoluteIndex( 0 );
  AtomNumber a2 = myatoms.getAbsoluteIndex( 1 );
  for(unsigned i=2; i<myatoms.getNumberOfAtoms(); ++i) {
    AtomNumber a3 = myatoms.getAbsoluteIndex( i );
    if( a3!=a1 && a3!=a2 ) calculateForThreeAtoms( i, d1, d1_len, bead, myatoms );
  }
  // std::vector<double> binvals( 1+maxbins ); for(unsigned i=1;i<maxbins;++i) binvals[i]=myatoms.getValue(i);
  // unsigned ii; double fdf;
  //std::cout<<"HELLO DENSITY "<<myatoms.getIndex(0)<<" "<<myatoms.getIndex(1)<<" "<<transformStoredValues( binvals, ii, fdf )<<std::endl;

  // Now find the element for which the density is maximal
  unsigned vout=2; double max=myatoms.getValue( 2 );
  for(unsigned i=3; i<myatoms.getUnderlyingMultiValue().getNumberOfValues()-1; ++i) {
    if( myatoms.getValue(i)>max ) { max=myatoms.getValue(i); vout=i; }
  }
  // Calculate value and derivative of switching function between atoms 1 and 2
  double dfuncl, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ),
                                         getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( d1_len, dfuncl );
  // Transform the density
  double df, tsw = threshold_switch.calculate( max, df );
  if( !doNotCalculateDerivatives() ) {
    // Factor of d1_len is required here because d1 is normalized
    d1 *= d1_len;
    addAtomDerivatives( 2+maxbins, 0, -dfuncl*d1, myatoms );
    addAtomDerivatives( 2+maxbins, 1, dfuncl*d1, myatoms );
    myatoms.addBoxDerivatives( 2+maxbins, (-dfuncl)*Tensor(d1,d1) );
    // Update active atoms so that next bit works
    updateActiveAtoms( myatoms );
    // Now finish caclulation of derivatives
    MultiValue& myvals=myatoms.getUnderlyingMultiValue();
    for(unsigned jd=0; jd<myvals.getNumberActive(); ++jd) {
      unsigned ider=myvals.getActiveIndex(jd);
      myvals.addDerivative( 1, ider, sw*df*max*myvals.getDerivative( vout, ider ) + tsw*myvals.getDerivative( 2+maxbins, ider ) );
    }
  }
  return sw*tsw;
}
void BondOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ) const {
  Vector distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );

  addAtomDerivatives( 2, 0, Vector(-1.0,0,0), myatoms );
  addAtomDerivatives( 2, 1, Vector(+1.0,0,0), myatoms );
  myatoms.addBoxDerivatives( 2, Tensor(distance,Vector(-1.0,0,0)) );
  myatoms.addValue( 2, distance[0] );

  addAtomDerivatives( 3, 0, Vector(0,-1.0,0), myatoms );
  addAtomDerivatives( 3, 1, Vector(0,+1.0,0), myatoms );
  myatoms.addBoxDerivatives( 3, Tensor(distance,Vector(0,-1.0,0)) );
  myatoms.addValue( 3, distance[1] );

  addAtomDerivatives( 4, 0, Vector(0,0,-1.0), myatoms );
  addAtomDerivatives( 4, 1, Vector(0,0,+1.0), myatoms );
  myatoms.addBoxDerivatives( 4, Tensor(distance,Vector(0,0,-1.0)) );
  myatoms.addValue( 4, distance[2] );
}
Esempio n. 9
0
void DFSClusterDiameter::performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const { 
  unsigned iatom=current/getNumberOfNodes(), jatom = current - iatom*getNumberOfNodes();
  Vector distance=getSeparation( getPosition(iatom), getPosition(jatom) );
  double dd = distance.modulo(), inv = 1.0/dd ; myvals.setValue( 1, dd ); 
  if( !doNotCalculateDerivatives() ){
      myvals.addDerivative( 1, 3*iatom + 0, -inv*distance[0] );
      myvals.addDerivative( 1, 3*iatom + 1, -inv*distance[1] );
      myvals.addDerivative( 1, 3*iatom + 2, -inv*distance[2] );
      myvals.addDerivative( 1, 3*jatom + 0, +inv*distance[0] );
      myvals.addDerivative( 1, 3*jatom + 1, +inv*distance[1] );
      myvals.addDerivative( 1, 3*jatom + 2, +inv*distance[2] );
      Tensor vir = -inv*Tensor(distance,distance);
      unsigned vbase = myvals.getNumberOfDerivatives() - 9;
      for(unsigned i=0;i<3;++i){
          for(unsigned j=0;j<3;++j) myvals.addDerivative( 1, vbase+3*i+j, vir(i,j) );
      }
  }
}
Esempio n. 10
0
void ContactAlignedMatrix::calculateWeight( const unsigned& taskCode, multicolvar::AtomValuePack& myatoms ) const {
  Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
  double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( distance.modulo(), dfunc );
  myatoms.setValue(0,sw);
}
Esempio n. 11
0
void Steinhardt::calculateVector(){
  double dfunc, dpoly_ass, md, tq6, itq6, real_z, imag_z; 
  Vector distance, dz, myrealvec, myimagvec, real_dz, imag_dz;
  // The square root of -1
  std::complex<double> ii( 0.0, 1.0 ), dp_x, dp_y, dp_z;

  double sw, poly_ass, dlen, nbond=0.0; std::complex<double> powered;
  for(unsigned i=1;i<getNAtoms();++i){
     distance=getSeparation( getPosition(0), getPosition(i) );
     dlen=distance.modulo(); sw = switchingFunction.calculate( dlen, dfunc );
     if( sw>=getTolerance() ){   
         nbond += sw;  // Accumulate total number of bonds
         double dlen3 = dlen*dlen*dlen;

         // Store derivatives of weight
         MultiColvarBase::addAtomsDerivatives( 0, getAtomIndex(0), (-dfunc)*distance );
         MultiColvarBase::addAtomsDerivatives( 0, getAtomIndex(i), (+dfunc)*distance );
         MultiColvarBase::addBoxDerivatives( 0, (-dfunc)*Tensor( distance,distance ) ); 

         // Do stuff for m=0
         poly_ass=deriv_poly( 0, distance[2]/dlen, dpoly_ass );
         // Derivatives of z/r wrt x, y, z
         dz = -( distance[2] / dlen3 )*distance; dz[2] += (1.0 / dlen);
         // Derivative wrt to the vector connecting the two atoms
         myrealvec = (+sw)*dpoly_ass*dz + poly_ass*(+dfunc)*distance;
         // Accumulate the derivatives
         addAtomsDerivative( tmom, 0, -myrealvec );      
         addAtomsDerivative( tmom, i, myrealvec ); 
         addBoxDerivatives( tmom, Tensor( -myrealvec,distance ) );
         // And store the vector function
         addComponent( tmom, sw*poly_ass );

         // The complex number of which we have to take powers
         std::complex<double> com1( distance[0]/dlen ,distance[1]/dlen );

         // Do stuff for all other m values
         for(unsigned m=1;m<=tmom;++m){
             // Calculate Legendre Polynomial
             poly_ass=deriv_poly( m, distance[2]/dlen, dpoly_ass );
             // Calculate powe of complex number
             powered=pow(com1,m-1); md=static_cast<double>(m);
             // Real and imaginary parts of z
             real_z = real(com1*powered); imag_z = imag(com1*powered );
 
             // Calculate steinhardt parameter
             tq6=poly_ass*real_z;   // Real part of steinhardt parameter
             itq6=poly_ass*imag_z;  // Imaginary part of steinhardt parameter

             // Derivatives wrt ( x/r + iy )^m
             dp_x = md*powered*( (1.0/dlen)-(distance[0]*distance[0])/dlen3-ii*(distance[0]*distance[1])/dlen3 );
             dp_y = md*powered*( ii*(1.0/dlen)-(distance[0]*distance[1])/dlen3-ii*(distance[1]*distance[1])/dlen3 );
             dp_z = md*powered*( -(distance[0]*distance[2])/dlen3-ii*(distance[1]*distance[2])/dlen3 );

             // Derivatives of real and imaginary parts of above
             real_dz[0] = real( dp_x ); real_dz[1] = real( dp_y ); real_dz[2] = real( dp_z );
             imag_dz[0] = imag( dp_x ); imag_dz[1] = imag( dp_y ); imag_dz[2] = imag( dp_z );  

             // Complete derivative of steinhardt parameter
             myrealvec = (+sw)*dpoly_ass*real_z*dz + (+dfunc)*distance*tq6 + (+sw)*poly_ass*real_dz; 
             myimagvec = (+sw)*dpoly_ass*imag_z*dz + (+dfunc)*distance*itq6 + (+sw)*poly_ass*imag_dz;

             // Real part
             addComponent( tmom+m, sw*tq6 );
             addAtomsDerivative( tmom+m, 0, -myrealvec );
             addAtomsDerivative( tmom+m, i, myrealvec );
             addBoxDerivatives( tmom+m, Tensor( -myrealvec,distance ) );
             // Imaginary part 
             addImaginaryComponent( tmom+m, sw*itq6 );
             addImaginaryAtomsDerivative( tmom+m, 0, -myimagvec );
             addImaginaryAtomsDerivative( tmom+m, i, myimagvec );
             addImaginaryBoxDerivatives( tmom+m, Tensor( -myimagvec,distance ) );
             // Store -m part of vector
             double pref=pow(-1.0,m); 
             // -m part of vector is just +m part multiplied by (-1.0)**m and multiplied by complex
             // conjugate of Legendre polynomial
             // Real part
             addComponent( tmom-m, pref*sw*tq6 );
             addAtomsDerivative( tmom-m, 0, -pref*myrealvec );
             addAtomsDerivative( tmom-m, i, pref*myrealvec );
             addBoxDerivatives( tmom-m, pref*Tensor( -myrealvec,distance ) );
             // Imaginary part
             addImaginaryComponent( tmom-m, -pref*sw*itq6 );
             addImaginaryAtomsDerivative( tmom-m, 0, pref*myimagvec );
             addImaginaryAtomsDerivative( tmom-m, i, -pref*myimagvec );
             addImaginaryBoxDerivatives( tmom-m, pref*Tensor( myimagvec,distance ) );
         }
     } else {
         removeAtomRequest( i, sw );
     }
  } 

  // Normalize 
  setElementValue(0, nbond ); updateActiveAtoms();
  for(unsigned i=0;i<2*getNumberOfComponentsInVector();++i) quotientRule( 5+i, 0, 5+i ); 
  // Clear tempory stuff
  clearDerivativesAfterTask(0);
}
Esempio n. 12
0
void ClusterDiameter::performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const { 
  unsigned iatom=std::floor(current/getNumberOfNodes()), jatom = current - iatom*getNumberOfNodes();
  Vector distance=getSeparation( getPosition(iatom), getPosition(jatom) );
  double dd = distance.modulo();
  myvals.setValue( 0, 1.0 ); myvals.setValue( 1, dd ); 
}
Esempio n. 13
0
double ContactMatrix::calculateWeight( const unsigned& taskCode, const double& weight, multicolvar::AtomValuePack& myatoms ) const {
  Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
  if( distance.modulo2()<switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).get_dmax2() ) return 1.0;
  return 0.0;
}
Esempio n. 14
0
void TopologyMatrix::calculateForThreeAtoms( const unsigned& iat, const Vector& d1, const double& d1_len,
    HistogramBead& bead, multicolvar::AtomValuePack& myatoms ) const {
  // Calculate if there are atoms in the cylinder (can use delta here as pbc are done in atom setup)
  Vector d2 = getSeparation( myatoms.getPosition(0), myatoms.getPosition(iat) );
  // Now calculate projection of d2 on d1
  double proj=dotProduct(d2,d1);
  // This tells us if we are outside the end of the cylinder
  double excess = proj - d1_len;
  // Return if we are outside of the cylinder as calculated based on excess
  if( excess>low_sf( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).get_dmax() ) return;
  // Find the length of the cylinder
  double binw = binw_mat( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) );
  double lcylinder = (std::floor( d1_len / binw ) + 1)*binw;
  // Return if the projection is outside the length of interest
  if( proj<-bead.getCutoff() || proj>(lcylinder+bead.getCutoff()) ) return;

  // Calculate the excess swiching function
  double edf, eval = low_sf( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( excess, edf );
  // Calculate the projection on the perpendicular distance from the center of the tube
  double cm = d2.modulo2() - proj*proj;

  // Now calculate the density in the cylinder
  if( cm<cylinder_sw( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).get_dmax2() ) {
    double dfuncr, val = cylinder_sw( getBaseColvarNumber( myatoms.getIndex(0) ),
                                      getBaseColvarNumber( myatoms.getIndex(1) ) ).calculateSqr( cm, dfuncr );
    double cellv = cell_volume( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) );
    Vector dc1, dc2, dc3, dd1, dd2, dd3, de1, de2, de3;
    if( !doNotCalculateDerivatives() ) {
      Tensor d1_a1;
      // Derivative of director connecting atom1 - atom2 wrt the position of atom 1
      d1_a1(0,0) = ( -(d1[1]*d1[1]+d1[2]*d1[2])/d1_len );   // dx/dx
      d1_a1(0,1) = (  d1[0]*d1[1]/d1_len );                 // dx/dy
      d1_a1(0,2) = (  d1[0]*d1[2]/d1_len );                 // dx/dz
      d1_a1(1,0) = (  d1[1]*d1[0]/d1_len );                 // dy/dx
      d1_a1(1,1) = ( -(d1[0]*d1[0]+d1[2]*d1[2])/d1_len );   // dy/dy
      d1_a1(1,2) = (  d1[1]*d1[2]/d1_len );
      d1_a1(2,0) = (  d1[2]*d1[0]/d1_len );
      d1_a1(2,1) = (  d1[2]*d1[1]/d1_len );
      d1_a1(2,2) = ( -(d1[1]*d1[1]+d1[0]*d1[0])/d1_len );

      // Calculate derivatives of dot product
      dd1 = matmul(d2, d1_a1) - d1;
      dd2 = matmul(d2, -d1_a1);
      dd3 = d1;

      // Calculate derivatives of cross product
      dc1 = dfuncr*( -d2 - proj*dd1 );
      dc2 = dfuncr*( -proj*dd2 );
      dc3 = dfuncr*( d2 - proj*dd3 );

      // Calculate derivatives of excess
      de1 = edf*excess*( dd1 + d1 );
      de2 = edf*excess*( dd2 - d1 );
      de3 = edf*excess*dd3;
    }

    Vector pos1 = myatoms.getPosition(0) + d1_len*d1;
    Vector pos2 = myatoms.getPosition(0) + d2;
    Vector g1derivf,g2derivf,lderivf; Tensor vir;
    for(unsigned bin=0; bin<maxbins; ++bin) {
      bead.set( bin*binw, (bin+1)*binw, sigma );
      if( proj<(bin*binw-bead.getCutoff()) || proj>binw*(bin+1)+bead.getCutoff() ) continue;
      double der, contr=bead.calculateWithCutoff( proj, der ) / cellv; der /= cellv;
      myatoms.addValue( 2+bin, contr*val*eval );

      if( !doNotCalculateDerivatives() ) {
        g1derivf=contr*eval*dc1 + val*eval*der*dd1 + contr*val*de1;
        addAtomDerivatives( 2+bin, 0, g1derivf, myatoms );
        g2derivf=contr*eval*dc2 + val*eval*der*dd2 + contr*val*de2;
        addAtomDerivatives( 2+bin, 1, g2derivf, myatoms );
        lderivf=contr*eval*dc3 + val*eval*der*dd3 + contr*val*de3;
        addAtomDerivatives( 2+bin, iat, lderivf, myatoms );
        // Virial
        vir = -Tensor( myatoms.getPosition(0), g1derivf ) - Tensor( pos1, g2derivf ) - Tensor( pos2, lderivf );
        myatoms.addBoxDerivatives( 2+bin, vir );
      }
    }
  }
}
Esempio n. 15
0
/**********************
lap: the upper RHS of the symmetric graph laplacian matrix which will be transformed
	to the hessian of the non-linear part of the optimisation function
	has dimensions num_variables, dummy vars do not have entries in lap
cs: array of pointers to separation constraints
***********************/
MosekEnv *mosek_init_sep(float *lap, int num_variables, int num_dummy_vars,
			 Constraint ** cs, int num_constraints)
{
    int i, j;
    MosekEnv *mskEnv = GNEW(MosekEnv);
    int count = 0;
    int nonzero_lapsize = num_variables * (num_variables - 1) / 2;
    /* fix var 0 */
    mskEnv->num_variables = num_variables + num_dummy_vars - 1;

    fprintf(stderr, "MOSEK!\n");
    logfile = fopen("quad_solve_log", "w");

    /* nonlinear coefficients matrix of objective function */
    mskEnv->qval = N_GNEW(nonzero_lapsize, double);
    mskEnv->qsubi = N_GNEW(nonzero_lapsize, int);
    mskEnv->qsubj = N_GNEW(nonzero_lapsize, int);

    /* solution vector */
    mskEnv->xx = N_GNEW(mskEnv->num_variables, double);

    /* pointer to beginning of nonzero sequence in a column */

    for (i = 0; i < num_variables - 1; i++) {
	for (j = i; j < num_variables - 1; j++) {
	    mskEnv->qval[count] = -2 * lap[count + num_variables];
	    /* assert(mskEnv->qval[count]!=0); */
	    mskEnv->qsubi[count] = j;
	    mskEnv->qsubj[count] = i;
	    count++;
	}
    }
#ifdef DUMP_CONSTRAINTS
    fprintf(logfile, "Q=[");
    count = 0;
    for (i = 0; i < num_variables - 1; i++) {
	if (i != 0)
	    fprintf(logfile, ";");
	for (j = 0; j < num_variables - 1; j++) {
	    if (j < i) {
		fprintf(logfile, "0 ");
	    } else {
		fprintf(logfile, "%f ", -2 * lap[num_variables + count++]);
	    }
	}
    }
    fprintf(logfile, "]\nQ=Q-diag(diag(Q))+Q'\n");
#endif
    /* Make the mosek environment. */
    mskEnv->r = MSK_makeenv(&mskEnv->env, NULL, NULL, NULL, NULL);

    /* Check whether the return code is ok. */
    if (mskEnv->r == MSK_RES_OK) {
	/* Directs the log stream to the user
	   specified procedure 'printstr'. */
	MSK_linkfunctoenvstream(mskEnv->env, MSK_STREAM_LOG, NULL,
				printstr);
    }

    /* Initialize the environment. */
    mskEnv->r = MSK_initenv(mskEnv->env);
    if (mskEnv->r == MSK_RES_OK) {
	/* Make the optimization task. */
	mskEnv->r =
	    MSK_maketask(mskEnv->env, num_constraints,
			 mskEnv->num_variables, &mskEnv->task);

	if (mskEnv->r == MSK_RES_OK) {
	    mskEnv->r =
		MSK_linkfunctotaskstream(mskEnv->task, MSK_STREAM_LOG,
					 NULL, printstr);
	    /* Resize the task. */
	    if (mskEnv->r == MSK_RES_OK)
		mskEnv->r = MSK_resizetask(mskEnv->task, num_constraints, mskEnv->num_variables, 0,	/* no cones!! */
					   /* number of non-zero constraint matrix entries:
					    *   each constraint applies to 2 vars
					    */
					   2 * num_constraints,
					   nonzero_lapsize);

	    /* Append the constraints. */
	    if (mskEnv->r == MSK_RES_OK)
		mskEnv->r = MSK_append(mskEnv->task, 1, num_constraints);

	    /* Append the variables. */
	    if (mskEnv->r == MSK_RES_OK)
		mskEnv->r =
		    MSK_append(mskEnv->task, 0, mskEnv->num_variables);
	    /* Put variable bounds. */
	    for (j = 0;
		 j < mskEnv->num_variables && mskEnv->r == MSK_RES_OK; j++)
		mskEnv->r =
		    MSK_putbound(mskEnv->task, 0, j, MSK_BK_RA,
				 -MSK_INFINITY, MSK_INFINITY);
	    for (i = 0; i < num_constraints; i++) {
		int u = getLeftVarID(cs[i]) - 1;
		int v = getRightVarID(cs[i]) - 1;
		double separation = getSeparation(cs[i]);
		if (u < 0) {
		    mskEnv->r =
			MSK_putbound(mskEnv->task, 0, v, MSK_BK_RA,
				     -MSK_INFINITY, -separation);
		    assert(mskEnv->r == MSK_RES_OK);
		} else if (v < 0) {
		    mskEnv->r =
			MSK_putbound(mskEnv->task, 0, u, MSK_BK_RA,
				     separation, MSK_INFINITY);
		    assert(mskEnv->r == MSK_RES_OK);
		} else {
		    /* fprintf(stderr,"u=%d,v=%d,sep=%f\n",u,v,separation); */
		    INIT_sub_val(u,v);
		    mskEnv->r =
			MSK_putavec(mskEnv->task, 1, i, 2, subi, vali);
		    assert(mskEnv->r == MSK_RES_OK);
		    mskEnv->r =
			MSK_putbound(mskEnv->task, 1, i, MSK_BK_LO,
				     separation, MSK_INFINITY);
		    assert(mskEnv->r == MSK_RES_OK);
		}
	    }
	    if (mskEnv->r == MSK_RES_OK) {
		/*
		 * The lower triangular part of the Q
		 * matrix in the objective is specified.
		 */
		mskEnv->r =
		    MSK_putqobj(mskEnv->task, nonzero_lapsize,
				mskEnv->qsubi, mskEnv->qsubj,
				mskEnv->qval);
		assert(mskEnv->r == MSK_RES_OK);
	    }
	}
    }
    return mskEnv;
}