void ManyRestraintsBase::applyChainRuleForDerivatives( const double& df ){ // Value (this could be optimized more -- GAT) for(unsigned i=0;i<aves->getNumberOfDerivatives();++i){ setElementDerivative( i, df*aves->getElementDerivative(i) ); } // And weights unsigned nder=aves->getNumberOfDerivatives(); for(unsigned i=0;i<aves->getNumberOfDerivatives();++i){ setElementDerivative( nder+i, aves->getElementDerivative(nder+i) ); } }
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; }
void BridgedMultiColvarFunction::clearDerivativesAfterTask( const unsigned& ider ){ unsigned vstart=getNumberOfDerivatives()*ider; if( derivativesAreRequired() ){ // Clear atom derivatives for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ unsigned iatom=vstart+3*atoms_with_derivatives[i]; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); } // Clear virial contribution unsigned nvir=vstart+3*mycolv->getNumberOfAtoms(); for(unsigned j=0;j<9;++j){ setElementDerivative( nvir, 0.0 ); nvir++; } // Clear derivatives of local atoms for(unsigned j=0;j<getNumberOfAtoms();++j){ setElementDerivative( nvir, 0.0 ); nvir++; setElementDerivative( nvir, 0.0 ); nvir++; setElementDerivative( nvir, 0.0 ); nvir++; } plumed_dbg_assert( (nvir-vstart)==getNumberOfDerivatives() ); } // Clear values thisval_wasset[ider]=false; setElementValue( ider, 0.0 ); thisval_wasset[ider]=false; }
void MultiColvarBase::quotientRule( const unsigned& uder, const unsigned& vder, const unsigned& iout ){ unsigned ustart=uder*getNumberOfDerivatives(); unsigned vstart=vder*getNumberOfDerivatives(); unsigned istart=iout*getNumberOfDerivatives(); double weight = getElementValue( vder ), pref = getElementValue( uder ) / (weight*weight); if( !doNotCalculateDerivatives() ){ for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ unsigned n=3*atoms_with_derivatives[i], nx=n, ny=n+1, nz=n+2; setElementDerivative( istart + nx, getElementDerivative(ustart+nx) / weight - pref*getElementDerivative(vstart+nx) ); setElementDerivative( istart + ny, getElementDerivative(ustart+ny) / weight - pref*getElementDerivative(vstart+ny) ); setElementDerivative( istart + nz, getElementDerivative(ustart+nz) / weight - pref*getElementDerivative(vstart+nz) ); } unsigned vbase=3*getNumberOfAtoms(); for(unsigned i=0;i<9;++i){ setElementDerivative( istart + vbase + i, getElementDerivative(ustart+vbase+i) / weight - pref*getElementDerivative(vstart+vbase+i) ); } } thisval_wasset[iout]=false; setElementValue( iout, getElementValue(uder) / weight ); }
void MultiColvarBase::clearDerivativesAfterTask( const unsigned& ider ){ unsigned vstart=getNumberOfDerivatives()*ider; thisval_wasset[ider]=false; setElementValue( ider, 0.0 ); thisval_wasset[ider]=false; if( ider>1 && ider<5 && derivativesAreRequired() ){ for(unsigned i=0;i<atomsWithCatomDer.getNumberActive();++i){ unsigned iatom=vstart+3*atomsWithCatomDer[i]; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); } } else if( derivativesAreRequired() ) { for(unsigned i=0;i<atoms_with_derivatives.getNumberActive();++i){ unsigned iatom=vstart+3*atoms_with_derivatives[i]; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); iatom++; setElementDerivative( iatom, 0.0 ); } unsigned nvir=vstart+3*getNumberOfAtoms(); for(unsigned j=0;j<9;++j){ setElementDerivative( nvir, 0.0 ); nvir++; } } }