Пример #1
0
void BridgeVessel::completeNumericalDerivatives(){
  unsigned nextra = myOutputAction->getNumberOfDerivatives() - getAction()->getNumberOfDerivatives();
  Matrix<double> tmpder( myOutputValues->getNumberOfComponents(), nextra );
  ActionWithVessel* vval=dynamic_cast<ActionWithVessel*>( myOutputAction );
  for(unsigned i=0;i<nextra;++i){
      vval->bridgeVariable=i; getAction()->calculate();
      for(int j=0;j<myOutputValues->getNumberOfComponents();++j) tmpder(j,i) = myOutputValues->getOutputQuantity(j);
  }
  vval->bridgeVariable=nextra; getAction()->calculate(); 
  plumed_assert( inum==mynumerical_values.size() ); inum=0;  // Reset inum now that we have finished calling calculate
  std::vector<double> base( myOutputValues->getNumberOfComponents() );
  for(int j=0;j<myOutputValues->getNumberOfComponents();++j) base[j] = myOutputValues->getOutputQuantity(j);

  const double delta=sqrt(epsilon);
  ActionAtomistic* aa=dynamic_cast<ActionAtomistic*>( getAction() );
  unsigned nvals=myOutputValues->getNumberOfComponents();
  for(unsigned j=0;j<nvals;++j) ( myOutputValues->copyOutput(j) )->clearDerivatives();   

  if( aa ){
      ActionWithArguments* aarg=dynamic_cast<ActionWithArguments*>( getAction() );
      plumed_assert( !aarg ); Tensor box=aa->getBox(); 
      unsigned natoms=aa->getNumberOfAtoms();
      for(unsigned j=0;j<nvals;++j){
          double ref=( myOutputValues->copyOutput(j) )->get();
          if( ( myOutputValues->copyOutput(j) )->getNumberOfDerivatives()>0 ){
              for(unsigned i=0;i<3*natoms;++i){
                  double d=( mynumerical_values[i*nvals+j] - ref)/delta;
                  ( myOutputValues->copyOutput(j) )->addDerivative(i,d);
              }
              Tensor virial;
              for(int i=0;i<3;i++) for(int k=0;k<3;k++){
                 virial(i,k)=( mynumerical_values[ nvals*(3*natoms + 3*i + k) + j ]-ref)/delta;
              }
              virial=-matmul(box.transpose(),virial);
              for(int i=0;i<3;i++) for(int k=0;k<3;k++) ( myOutputValues->copyOutput(j) )->addDerivative(3*natoms+3*k+i,virial(k,i));
          }
      }
  } else {
      plumed_merror("not implemented or tested yet");
//      unsigned nder=myOutputAction->getNumberOfDerivatives();
//      for(unsigned j=0;j<nvals;++j){
//          double ref=( myOutputValues->copyOutput(j) )->get();
//              for(unsigned i=0;i<nder;++i){
//                  double d=( mynumerical_values[i*nvals+j] - ref)/delta;
//                  ( myOutputValues->copyOutput(j) )->addDerivative(i,d);
//              }
//          }
//      }
  }
  // Add the derivatives wrt to the local quantities we are working with
  for(unsigned j=0;j<nvals;++j){
     unsigned k=0;
     for(unsigned i=getAction()->getNumberOfDerivatives();i<myOutputAction->getNumberOfDerivatives();++i){
        ( myOutputValues->copyOutput(j) )->addDerivative( i, (tmpder(j,k)-base[j])/sqrt(epsilon) ); k++;
     }
  }
}
void Molecular_system::locDerivative(int ion, Sample_point * sample,
                                     Force_fitter & fitter,
                                     Array1 <doublevar> & der) {

  sample->updateEIDist();
  der.Resize(3);
  der=0;
  Array1 <doublevar> R(5);
  int ne=sample->electronSize();
  Array1 <doublevar> tmpder(3), tmpder_fit(3);
  for(int e=0; e< ne; e++) {
    sample->getEIDist(e,ion, R);
    for(int d=0; d< 3; d++) 
      //der(d)-=sample->getIonCharge(ion)*R(d+2)/(R(1)*R(0));
      tmpder(d)=-sample->getIonCharge(ion)*R(d+2)/(R(1)*R(0));
    fitter.fit_force(R,tmpder, tmpder_fit);
    for(int d=0; d< 3; d++)
      der(d)+=tmpder_fit(d);
  }

  Array1 <doublevar> vec(3);
  Array1 <doublevar> r_ion(3);
  sample->getIonPos(ion, r_ion);

  int nIon=sample->ionSize();

  for(int j=0; j< nIon; j++) {
    if(j!=ion) {
    sample->getIonPos(j,R);
    doublevar r2=0;
    for(int d=0; d <3; d++) 
      vec(d)=r_ion(d)-R(d);

    for(int d=0; d< 3; d++)
      r2+=vec(d)*vec(d);
    doublevar r=sqrt(r2);

    for(int d=0; d< 3; d++) 
      der(d)-=sample->getIonCharge(ion)*sample->getIonCharge(j)*vec(d)/(r2*r);
    }
  }

}
Пример #3
0
void BiasRepresentation::pushKernel( IFile *ifile ){
        KernelFunctions *kk;
        // here below the reading of the kernel is completely hidden
        if(histosigma.size()==0){ 
		ifile->allowIgnoredFields();
 		kk=KernelFunctions::read(ifile,names)   ;
        }else{
		// when doing histogram assume gaussian with a given diagonal sigma 
		// and neglect all the rest
 		kk=readFromPoint(ifile)   ;
        }
 	hills.push_back(kk);		
	// the bias factor is not something about the kernels but 
	// must be stored to keep the  bias/free energy duality
	string dummy; double dummyd;
	if(ifile->FieldExist("biasf")){
		ifile->scanField("biasf",dummy);
	        Tools::convert(dummy,dummyd);
	}else{dummyd=1.0;}
	biasf.push_back(dummyd);
        // the domain does not pertain to the kernel but to the values here defined 
	string	mins,maxs,minv,maxv,mini,maxi;mins="min_";maxs="max_";
        for(int i=0 ; i<ndim; i++){
            if(values[i]->isPeriodic()){		
	      ifile->scanField(mins+names[i],minv);		
	      ifile->scanField(maxs+names[i],maxv);		
	      // verify that the domain is correct 
              values[i]->getDomain(mini,maxi);
	      plumed_massert(mini==minv,"the input periodicity in hills and in value definition does not match"  ); 	
	      plumed_massert(maxi==maxv,"the input periodicity in hills and in value definition does not match"  ); 	
	    }
        }
        // if grid is defined then it should be added on the grid    
 	//cerr<<"now with "<<hills.size()<<endl;
        if(hasgrid){
                 vector<unsigned> nneighb=kk->getSupport(BiasGrid_->getDx());
                 vector<unsigned> neighbors=BiasGrid_->getNeighbors(kk->getCenter(),nneighb);
                 vector<double> der(ndim);
                 vector<double> xx(ndim);
                 if(mycomm.Get_size()==1){
                  for(unsigned i=0;i<neighbors.size();++i){
                   unsigned ineigh=neighbors[i];
                   for(int j=0;j<ndim;++j){der[j]=0.0;}
                   BiasGrid_->getPoint(ineigh,xx);   
                   // assign xx to a new vector of values
                   for(int j=0;j<ndim;++j){values[j]->set(xx[j]);}	 
                   double bias=kk->evaluate(values,der,true);
		   if(rescaledToBias){
			double f=(biasf.back()-1.)/(biasf.back());
			bias*=f;
			for(int j=0;j<ndim;++j){der[j]*=f;}
                   }
                   BiasGrid_->addValueAndDerivatives(ineigh,bias,der);
                  } 
                 } else {
                  unsigned stride=mycomm.Get_size();
                  unsigned rank=mycomm.Get_rank();
                  vector<double> allder(ndim*neighbors.size(),0.0);
                  vector<double> allbias(neighbors.size(),0.0);
	          vector<double> tmpder(ndim); 
                  for(unsigned i=rank;i<neighbors.size();i+=stride){
                   unsigned ineigh=neighbors[i];
                   BiasGrid_->getPoint(ineigh,xx);
                   for(int j=0;j<ndim;++j){values[j]->set(xx[j]);}	 
                   allbias[i]=kk->evaluate(values,tmpder,true);
		   if(rescaledToBias){
			double f=(biasf.back()-1.)/(biasf.back());
			allbias[i]*=f;
			for(int j=0;j<ndim;++j){tmpder[j]*=f;}
                   }
 	           // this solution with the temporary vector is rather bad, probably better to take 		
		   // a pointer of double as it was in old gaussian 
                   for(int j=0;j<ndim;++j){ allder[ndim*i+j]=tmpder[j];tmpder[j]=0.;}
                  }
                  mycomm.Sum(allbias);
                  mycomm.Sum(allder);
                  for(unsigned i=0;i<neighbors.size();++i){
                   unsigned ineigh=neighbors[i];
                   for(int j=0;j<ndim;++j){der[j]=allder[ndim*i+j];}
                   BiasGrid_->addValueAndDerivatives(ineigh,allbias[i],der);
                  }
                }
        }
}