Beispiel #1
0
      /**
       * Search for a roughly reasonable (within a factor of 2)
       * setting of the step size epsilon.
       */
      virtual void find_reasonable_parameters() {
        this->_epsilon = 1.0;
        std::vector<double> x = this->_x;
        std::vector<double> m(this->_model.num_params_r());
        for (size_t i = 0; i < m.size(); ++i)
          m[i] = this->_rand_unit_norm();
        std::vector<double> g = this->_g;
        double lastlogp = this->_logp;
        double logp = leapfrog(this->_model, this->_z, x, m, g, this->_epsilon);
        double H = logp - lastlogp;
        int direction = H > log(0.5) ? 1 : -1;
        while (1) {
          x = this->_x;
          g = this->_g;
          for (size_t i = 0; i < m.size(); ++i)
            m[i] = this->_rand_unit_norm();
          logp = leapfrog(this->_model, this->_z, x, m, g, this->_epsilon);
          H = logp - lastlogp;
          if ((direction == 1) && !(H > log(0.5)))
            break;
          else if ((direction == -1) && !(H < log(0.5)))
            break;
          else
            this->_epsilon = ( (direction == 1) 
                               ? 2.0 * this->_epsilon 
                               : 0.5 * this->_epsilon );

          if (this->_epsilon > 1e300)
            throw std::runtime_error("Posterior is improper. Please check your model.");
          if (this->_epsilon == 0)
            throw std::runtime_error("No acceptably small step size could be found. Perhaps the posterior is not continuous?");
        }
      }
Beispiel #2
0
int main(){

  /*
   * Variables
   */

  FLOAT delta_t = 0.001; //Potencia de 10
  FLOAT init_t = 0;
  FLOAT final_t = 1;
  int  n_points = (int)( ( final_t - init_t ) / delta_t );
  int n_masses = 10000;
  FLOAT *x0 , *y0, *z0;
  FLOAT *vx0 , *vy0, *vz0;

  /*
   *Inicializaion
   */  
  FLOAT **xyz = initpos(n_masses);
  x0 = xyz[0];
  y0 = xyz[1];
  z0 = xyz[2]; 

  FLOAT **vxyz = initvel(n_masses);
  vx0 = vxyz[0];
  vy0 = vxyz[1];
  vz0 = vxyz[2]; 
  /*
   *Bono, por favor :)
   */
  leapfrog(x0 , y0 , z0 , vx0 , vy0, vz0 ,
	   delta_t , n_points , n_masses);
  return 0;
}
Beispiel #3
0
int main(void)
{
	//stampo le distanze dall'origine dopo 100000 iterazioni con i due metodi: quale sarà la più grande?
	std::cout << euler(0.02, 100000) << "\n";
	std::cout << leapfrog(0.02,100000)<< "\n";
	
	return 0;
}
Beispiel #4
0
int main(void){
  int p;
    
  lospol();
	
  	for(p=0;p<20000;p++){
  		leapfrog(p);
}
    printhist();
}
Beispiel #5
0
void lpf_int(char *fout,double t, double tmax, double step, double x, double zx, double v, double zv){
    /* Default integration parameters and initial conditions: */
    int i;
    double E;
    FILE *file;
    file=fopen(fout,"w");
    if (t > 0) advance_vel(x, &zx, -0.5*step);
    if (t > 0) advance_vel(v, &zv, -0.5*step);
    E=(zx*zx+zv*zv)/2.0+(-1)/(sqrt(1+2*x*x+2*v*v));
    printf("%f\t%e\t%e\t%e\t%e\t%e\n", t, x,zx,v,zv,E);
    fprintf(file,"%f\t%e\t%e\t%e\t%e\t%e\n", t, x,zx,v,zv,E);
    advance_vel(x,&zx, 0.5*step);
    advance_vel(v,&zv, 0.5*step);
    while (t < tmax) {
      leapfrog(&x, &zx, &t, step);
      leapfrog(&v, &zv, &t, step);
      E=(zx*zx+zv*zv)/2.0+(-1)/(sqrt(1+2*x*x+2*v*v));
      printf("%f\t%e\t%e\t%e\t%e\t%e\n", t, x,zx,v,zv,E);
      fprintf(file,"%f\t%e\t%e\t%e\t%e\t%e\n", t, x,zx,v,zv,E);
    }
}
Beispiel #6
0
//function epsilon = find_reasonable_epsilon(theta0, grad0, logp0, f)
double find_reasonable_epsilon(const double *theta0, const double *grad0, const double logp0, const mxArray *f, 
							   const int D, std::mt19937 &generator, std::normal_distribution<double> &stdnrm, 
							   double *r0, mxArray *thetaprimemat, double *rprime, double *gradprime) {
//	epsilon = 1;
	double epsilon = 1.0;
//	r0 = randn(1, length(theta0));
	for (int i = 0; i < D; ++i) {
		r0[i] = stdnrm(generator);
	}
//	[~, rprime, ~, logpprime] = leapfrog(theta0, r0, grad0, epsilon, f);
	double logpprime;
	leapfrog(theta0, r0, grad0, epsilon, f, D, thetaprimemat, rprime, gradprime, &logpprime);
//	acceptprob = exp(logpprime - logp0 - 0.5 * (rprime * rprime' - r0 * r0'));
	double acceptprob = 0.0;
	for (int i = 0; i < D; ++i) {
		acceptprob += (r0[i] + rprime[i]) * (r0[i] - rprime[i]);
	}
	acceptprob = exp(logpprime - logp0 + 0.5 * acceptprob);
//	a = 2 * (acceptprob > 0.5) - 1;
	bool a = acceptprob > 0.5;
	const double twopowa = (a ? 2 : 0.5);
//	while (acceptprob^a > 2^(-a))
	double acceptprobpowa = (a ? acceptprob : 1.0/acceptprob);
	while (acceptprobpowa * twopowa > 1) {
//		epsilon = epsilon * 2^a;
		epsilon *= twopowa;
//		[~, rprime, ~, logpprime] = leapfrog(theta0, r0, grad0, epsilon, f);
		leapfrog(theta0, r0, grad0, epsilon, f, D, thetaprimemat, rprime, gradprime, &logpprime);
//		acceptprob = exp(logpprime - logp0 - 0.5 * (rprime * rprime' - r0 * r0'));
		acceptprob = 0.0;
		for (int i = 0; i < D; ++i) {
			acceptprob += (r0[i] + rprime[i]) * (r0[i] - rprime[i]);
		}
		acceptprob = logpprime - logp0 + 0.5 * acceptprob;
		acceptprobpowa = (a ? exp(acceptprob) : exp(-acceptprob));
//	end
	}
//end
  	return epsilon;
}
Beispiel #7
0
void lpf_int(double t, double tmax, double step, double x, double v)
{
    /* Default integration parameters and initial conditions: */
    int i;
    
    output(x, v, t, step);
    advance_vel(x, &v, 0.5*step);
    while (t < tmax) {
	leapfrog(&x, &v, &t, step);
	if (t > 0) advance_vel(x, &v, -0.5*step);
	printf("%f\t%f\t%f\n", t, sin(t),x);
	//output(x, v, t, step);
    }
}
Beispiel #8
0
int update() //Basic HMC update step
{
  double squnrm;
  int i, acc;
  double exphdiff;
  
  /* the new impulses and the 'generator' of the arbitrary pseudofield */
  /* calculate the hamiltonian of this state: new impulses + action */
  /* g_X is ab-used a bit - here it is \xi = (gamma5 D)^{-1} \phi */
  
  ham_old = s_g_old;
  for(i=0; i<GRIDPOINTS; i++) {
    gp1[i] = gauss();
    gp2[i] = gauss();
    ham_old += 0.5*(gp1[i]*gp1[i] + gp2[i]*gp2[i]);
  }
  
  /* Now create the field and calculate its contributions to the action (end of the 'misuse') */
  /* squnrm is the fermion part of the action : */
  /*   S = R^dagger * R  =  g_fermion^dag * D^{-1 dag} * D^{-1} * g_fermion = g_fermion Q^-1 g_fermion */

  /* PF1 det(1/(Q^2 + mu^2)) */
  for(i=0; i<GRIDPOINTS; i++) {
    g_X[i].s1 = (gauss() + I*gauss())/sqrt(2); //Gaussian fields R
    g_X[i].s2 = (gauss() + I*gauss())/sqrt(2);
  }
  squnrm = square_norm(g_X);
  
  // step iv): g_fermion = \phi = K^dag * g_X = K^dag * \xi
  gam5D_wilson(g_fermion, g_X);
  assign_diff_mul(g_fermion, g_X, 0.+I*sqrt(g_musqr));
  ham_old += squnrm;

  /* PF2 det((Q^2 + mu^2)/Q^2) */
  if(no_timescales > 2) {
    for(i=0; i<GRIDPOINTS; i++) {
      g_X[i].s1 = (gauss() + I*gauss())/sqrt(2); //Gaussian fields R
      g_X[i].s2 = (gauss() + I*gauss())/sqrt(2);
    }
    squnrm = square_norm(g_X);

    cg(g_fermion2, g_X, ITER_MAX, DELTACG, &gam5D_SQR_musqr_wilson);    
    gam5D_wilson(g_gam5DX, g_fermion2);
    assign_add_mul(g_gam5DX, g_fermion2, 0.+I*sqrt(g_musqr));
    gam5D_wilson(g_fermion2, g_gam5DX);
    ham_old += squnrm;
  }
  // Add the part for the fermion fields

  // Do the molecular dynamic chain
  /* the simple LF scheme */

  /* the second order minimal norm multi-timescale integrator*/
  /* MN2_integrator(g_steps, 2, g_steps*g_stepsize, 0.2); */

  /* This is the recursive implementation */
  /* in can be found in rec_lf_integrator.c|h */
  if (no_timescales == 1)
    leapfrog(n_steps[0], tau/n_steps[0]);
  else
    integrate_leap_frog(tau/n_steps[no_timescales-1], no_timescales-1, no_timescales, n_steps, 1, up_momenta);
  
  // Calculate the new action and hamiltonian
  ham = 0;
  s_g = 0;
  for (i=0; i<GRIDPOINTS; i++) {
    s_g += S_G(i);
    ham += 0.5*(gp1[i]*gp1[i] + gp2[i]*gp2[i]);
  }
  /* Sum_ij [(g_fermion^*)_i (Q^-1)_ij (g_fermion)_j]  =  Sum_ij [(g_fermion^*)_i (g_X)_i] */
  ham += s_g;
  // add in the part for the fermion fields.
  cg(g_X, g_fermion, ITER_MAX, DELTACG, &gam5D_SQR_musqr_wilson);
  ham += scalar_prod_r(g_fermion, g_X);
  
  if(no_timescales > 2) {
    cg(g_gam5DX, g_fermion2, ITER_MAX, DELTACG, &gam5D_SQR_wilson);
    gam5D_SQR_musqr_wilson(g_X, g_temp, g_gam5DX);
    ham += scalar_prod_r(g_fermion2, g_X);
  }

  exphdiff = exp(ham_old-ham);
  acc = accept(exphdiff);
 
  for(i=0; i<GRIDPOINTS; i++) {
    gauge1_old[i]=gauge1[i];
    gauge2_old[i]=gauge2[i];
  }
 
  s_g_old = s_g;
  return(acc);
}
Beispiel #9
0
void function_minimizer::shmc_mcmc_routine(int nmcmc,int iseed0,double dscale,
					  int restart_flag) {

  if (nmcmc<=0)
    {
      cerr << endl << "Error: Negative iterations for MCMC not meaningful" << endl;
      ad_exit(1);
    }

  uostream * pofs_psave=NULL;
  if (mcmc2_flag==1)
    {
      initial_params::restore_start_phase();
    }
  initial_params::set_inactive_random_effects();
  initial_params::set_active_random_effects();
  int nvar_re=initial_params::nvarcalc();
  int nvar=initial_params::nvarcalc(); // get the number of active parameters
  if (mcmc2_flag==0)
    {
      initial_params::set_inactive_random_effects();
      nvar=initial_params::nvarcalc(); // get the number of active parameters
    }
  initial_params::restore_start_phase();

  independent_variables parsave(1,nvar_re);
  // dvector x(1,nvar);
  // initial_params::xinit(x);
  // dvector pen_vector(1,nvar);
  // {
  //   initial_params::reset(dvar_vector(x),pen_vector);
  // }
  initial_params::mc_phase=1;

  int old_Hybrid_bounded_flag=-1;
  int on,nopt = 0;

  //// ------------------------------ Parse input options
  // Step size. If not specified, will be adapted. If specified must be >0
  // and will not be adapted.
  double eps=0.1;
  double _eps=-1.0;
  int useDA=1; 			// whether to adapt step size
  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-hyeps",nopt))>-1)
    {
      if (!nopt) // not specified means to adapt, using function below to find reasonable one
	{
	  cerr << "Warning: No step size given after -hyeps, ignoring" << endl;
	  useDA=1;
	}
      else			// read in specified value and do not adapt
	{
	  istringstream ist(ad_comm::argv[on+1]);
	  ist >> _eps;
	  if (_eps<=0)
	    {
	      cerr << "Error: step size (-hyeps argument) needs positive number";
	      ad_exit(1);
	    }
	  else
	    {
	      eps=_eps;
	      useDA=0;
	    }
	}
    }
  // Chain number -- for console display purposes only
  int chain=1;
  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-chain",nopt))>-1) {
    if (nopt) {
      int iii=atoi(ad_comm::argv[on+1]);
      if (iii <1) {
	cerr << "Error: chain must be >= 1" << endl;
	ad_exit(1);
      } else {
	chain=iii;
      }
    }
  }
  // Number of leapfrog steps. Defaults to 10.
  int L=10;
  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-hynstep",nopt))>-1)
    {
      if (nopt)
	{
	  int _L=atoi(ad_comm::argv[on+1]);
	  if (_L < 1 )
	    {
	      cerr << "Error: hynstep argument must be integer > 0 " << endl;
	      ad_exit(1);
	    }
	  else
	    {
	      L=_L;
	    }
	}
    }

  // Number of warmup samples if using adaptation of step size. Defaults to
  // half of iterations.
  int nwarmup= (int)nmcmc/2;
  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-nwarmup",nopt))>-1)
    {
      if (nopt)
        {
          int iii=atoi(ad_comm::argv[on+1]);
          if (iii <=0 || iii > nmcmc)
	    {
	      cerr << "Error: nwarmup must be 0 < nwarmup < nmcmc" << endl;
	      ad_exit(1);
	    }
          else
	    {
	      nwarmup=iii;
	    }
        }
    }

  // Target acceptance rate for step size adaptation. Must be
  // 0<adapt_delta<1. Defaults to 0.8.
  double adapt_delta=0.8; // target acceptance rate specified by the user
  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-adapt_delta",nopt))>-1)
    {
      if (nopt)
	{
	  istringstream ist(ad_comm::argv[on+1]);
	  double _adapt_delta;
	  ist >> _adapt_delta;
	  if (_adapt_delta < 0 || _adapt_delta > 1 )
	    {
	      cerr << "Error: adapt_delta must be between 0 and 1"
		" using default of 0.8" << endl;
	    }
	  else
	    {
	      adapt_delta=_adapt_delta;
	    }
	}
    }
  // Use diagnoal covariance (identity mass matrix)
  int diag_option=0;
  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcdiag"))>-1)
    {
      diag_option=1;
      cout << " Setting covariance matrix to diagonal with entries " << dscale
	   << endl;
    }
  // Restart chain from previous run?
  int mcrestart_flag=option_match(ad_comm::argc,ad_comm::argv,"-mcr");
  if(mcrestart_flag > -1){
    cerr << endl << "Error: -mcr option not implemented for HMC" << endl;
    ad_exit(1);
  }

  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcec"))>-1)
    {
      cerr << endl << "Error: -mcec option not yet implemented with HMC" << endl;
      ad_exit(1);
      // use_empirical_flag=1;
      // read_empirical_covariance_matrix(nvar,S,ad_comm::adprogram_name);
    }

  // Prepare the mass matrix for use. Depends on many factors below.
  dmatrix S(1,nvar,1,nvar);
  dvector old_scale(1,nvar);
  int old_nvar;
  // Need to grab old_scale values still, since it is scaled below
  read_covariance_matrix(S,nvar,old_Hybrid_bounded_flag,old_scale);
  if (diag_option)		// set covariance to be diagonal
    {
      S.initialize();
      for (int i=1;i<=nvar;i++)
	{
	  S(i,i)=dscale;
	}
    }

  // How much to thin, for now fixed at 1.
  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-mcsave"))>-1)
    {
      cerr << "Option -mcsave does not currently work with HMC -- every iteration is saved" << endl;
      ad_exit(1);
    }
  //// ------------------------------ End of input processing


  //// Setup more inputs and outputs
  pofs_psave=
    new uostream((char*)(ad_comm::adprogram_name + adstring(".psv")));
  if (!pofs_psave|| !(*pofs_psave))
    {
      cerr << "Error trying to open file" <<
	ad_comm::adprogram_name + adstring(".psv") << endl;
      ad_exit(1);
    }
  if (mcrestart_flag == -1 )
    {
      (*pofs_psave) << nvar;
    }
  // need to rescale the hessian
  // get the current scale
  dvector x0(1,nvar);
  dvector current_scale(1,nvar);
  initial_params::xinit(x0);
  int mctmp=initial_params::mc_phase;
  initial_params::mc_phase=0;
  initial_params::stddev_scale(current_scale,x0);
  initial_params::mc_phase=mctmp;
  // cout << "old scale=" <<  old_scale << endl;
  // cout << "current scale=" << current_scale << endl;
  // cout << "S before=" << S << endl;
  // I think this is only needed if mcmc2 is used??
  // for (int i=1;i<=nvar;i++)
  //   {
  //     for (int j=1;j<=nvar;j++)
  // 	{
  // 	  S(i,j)*=old_scale(i)*old_scale(j);
  // 	}
  //   }
  if(diag_option){
    for (int i=1;i<=nvar;i++)
      {
	for (int j=1;j<=nvar;j++)
	  {
	    S(i,j)*=current_scale(i)*current_scale(j);
	  }
      }
  }
  //  cout << "S after=" << S << endl;
  gradient_structure::set_NO_DERIVATIVES();
  if (mcmc2_flag==0)
    {
      initial_params::set_inactive_random_effects();
    }
  // Setup random number generator, based on seed passed
  int iseed=2197;
  if (iseed0) iseed=iseed0;
  random_number_generator rng(iseed);
  gradient_structure::set_YES_DERIVATIVES();
  initial_params::xinit(x0);

  // Dual averaging components
  dvector epsvec(1,nmcmc+1), epsbar(1,nmcmc+1), Hbar(1,nmcmc+1);
  epsvec.initialize(); epsbar.initialize(); Hbar.initialize();
  double time_warmup=0;
  double time_total=0;
  std::clock_t start = clock();
  time_t now = time(0);
  tm* localtm = localtime(&now);
  cout << endl << "Starting static HMC for model '" << ad_comm::adprogram_name <<
    "' at " << asctime(localtm);
  // write sampler parameters
  ofstream adaptation("adaptation.csv", ios::trunc);
  adaptation << "accept_stat__,stepsize__,int_time__,energy__,lp__" << endl;

  // Declare and initialize the variables needed for the algorithm
  dmatrix chd = choleski_decomp(S); // cholesky decomp of mass matrix
  dvector y(1,nvar); // unbounded parameters
  y.initialize();
  // transformed params
  independent_variables z(1,nvar); z=chd*y;
  dvector gr(1,nvar);		// gradients in unbounded space
  // Need to run this to fill gr with current gradients and initial NLL.
  double nllbegin=get_hybrid_monte_carlo_value(nvar,z,gr);
  if(std::isnan(nllbegin)){
    cerr << "Starting MCMC trajectory at NaN -- something is wrong!" << endl;
    ad_exit(1);
  }
  // initial rotated gradient
  dvector gr2(1,nvar); gr2=gr*chd;
  dvector p(1,nvar);		// momentum vector
  p.fill_randn(rng);
  // Copy initial value to parsave in case first trajectory rejected
  initial_params::copy_all_values(parsave,1.0);
  double iaccept=0.0;
  // The gradient and params at beginning of trajectory, in case rejected.
  dvector gr2begin(1,nvar); gr2begin=gr2;
  dvector ybegin(1,nvar); ybegin=y;
  double nll=nllbegin;
  // if(useDA){
  //   eps=find_reasonable_stepsize(nvar,y,p,chd);
  //   epsvec(1)=eps; epsbar(1)=eps; Hbar(1)=0;
  // }
  double mu=log(10*eps);

  // Start of MCMC chain
  for (int is=1;is<=nmcmc;is++) {
    // Random momentum for next iteration, only affects Ham values
    p.fill_randn(rng);
    double H0=nll+0.5*norm2(p);

    // Generate trajectory
    int divergence=0;
    for (int i=1;i<=L;i++) {
      // leapfrog updates gr, p, y, and gr2 by reference
      nll=leapfrog(nvar, gr, chd, eps, p, y, gr2);
      // Break trajectory early if a divergence occurs to save computation
      if(std::isnan(nll)){
	divergence=1; break;
      }
    } // end of trajectory

    // Test whether to accept the proposed state
    double Ham=nll+0.5*norm2(p); // Update Hamiltonian for proposed set
    double alpha=min(1.0, exp(H0-Ham)); // acceptance ratio
    double rr=randu(rng);	   // Runif(1)
    if (rr<alpha && !divergence){ // accept
      iaccept++;
      // Update for next iteration: params, Hamiltonian and gr2
      ybegin=y;
      gr2begin=gr2;
      nllbegin=nll;
      initial_params::copy_all_values(parsave,1.0);
    } else {
      // Reject and don't update anything to reuse initials for next trajectory
      y=ybegin;
      gr2=gr2begin;
      nll=nllbegin;
    }
    // Save parameters to psv file, duplicated if rejected
    (*pofs_psave) << parsave;

    // Adaptation of step size (eps).
    if(useDA && is <= nwarmup){
      eps=adapt_eps(is, eps,  alpha, adapt_delta, mu, epsvec, epsbar, Hbar);
    }
    adaptation << alpha << "," <<  eps << "," << eps*L << "," << H0 << "," << -nll << endl;
    if(is ==nwarmup) time_warmup = ( std::clock()-start)/(double) CLOCKS_PER_SEC;
    print_mcmc_progress(is, nmcmc, nwarmup, chain);
  } // end of MCMC chain

  // This final ratio should closely match adapt_delta
  if(useDA){
    cout << "Final acceptance ratio=" << iaccept/nmcmc << " and target is " << adapt_delta<<endl;
    cout << "Final step size=" << eps << "; after " << nwarmup << " warmup iterations"<< endl;
  } else {
    cout << "Final acceptance ratio=" << iaccept/nmcmc << endl;
  }

  time_total = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
  print_mcmc_timing(time_warmup, time_total);

  // I assume this closes the connection to the file??
  if (pofs_psave)
    {
      delete pofs_psave;
      pofs_psave=NULL;
    }
} // end of HMC function
Beispiel #10
0
//function [thetaminus, rminus, gradminus, thetaplus, rplus, gradplus, thetaprime, gradprime, logpprime, nprime, sprime, alphaprime, nalphaprime] = ...
//				build_tree(theta, r, grad, logu, v, j, epsilon, f, joint0)
void build_tree(const double *theta, const double *r, const double *grad, 
				const double logu, const bool v, const int j, const double epsilon, const mxArray *f, const double joint0, 
			    const int D, std::mt19937 &generator, std::uniform_real_distribution<double> &uni01, 
			    double *thetaminus, double *rminus, double *gradminus, double *thetaplus, double *rplus, double *gradplus, 
			    mxArray *thetaprimemat, double *rprime, double *gradprime, double *logpprime, 
			    double *nprime, bool *sprime, double *alphaprime, double *nalphaprime) {
	double *thetaprime = mxGetPr(thetaprimemat);
	const size_t sz = D*sizeof(double);
	
//	if (j == 0)
	if (j == 0) {
//		[thetaprime, rprime, gradprime, logpprime] = leapfrog(theta, r, grad, v*epsilon, f);
		leapfrog(theta, r, grad, (v ? epsilon : -epsilon), f, D, thetaprimemat, rprime, gradprime, logpprime);
//		joint = logpprime - 0.5 * (rprime * rprime');
		double joint = 0.0;
		for (int i = 0; i < D; ++i) {
			joint += rprime[i]*rprime[i];
		}
		joint = *logpprime - 0.5 * joint;
//		nprime = logu < joint;
		*nprime = logu < joint;
//		sprime = logu - 1000 < joint;
		*sprime = (logu - 1000.0) < joint;
//		thetaminus = thetaprime;
//		thetaplus = thetaprime;
//		rminus = rprime;
//		rplus = rprime;
//		gradminus = gradprime;
//		gradplus = gradprime;
		if (thetaminus) memcpy(thetaminus, thetaprime, sz);
		if (rminus) memcpy(rminus, rprime, sz);
		if (gradminus) memcpy(gradminus, gradprime, sz);
		if (thetaplus) memcpy(thetaplus, thetaprime, sz);
		if (rplus) memcpy(rplus, rprime, sz);
		if (gradplus) memcpy(gradplus, gradprime, sz);
//		alphaprime = min(1, exp(logpprime - 0.5 * (rprime * rprime') - joint0));
		*alphaprime = std::min(1.0, exp(joint - joint0));
//		nalphaprime = 1;
		*nalphaprime = 1.0;
//	else
	} else {
//		[thetaminus, rminus, gradminus, thetaplus, rplus, gradplus, thetaprime, gradprime, logpprime, nprime, sprime, alphaprime, nalphaprime] = ...
//					build_tree(theta, r, grad, logu, v, j-1, epsilon, f, joint0);
		double *thetaminusout = new double [D];
		double *rminusout = new double [D];
		double *gradminusout = new double [D];
		double *thetaplusout = new double [D];
		double *rplusout = new double [D];
		double *gradplusout = new double [D];
		build_tree(theta, r, grad, logu, v, j-1, epsilon, f, joint0, D, generator, uni01, 
				   thetaminusout, rminusout, gradminusout, thetaplusout, rplusout, gradplusout, 
				   thetaprimemat, rprime, gradprime, logpprime, nprime, sprime, alphaprime, nalphaprime);
//		if (sprime == 1)
		if (*sprime == true) {
			double *thetaprimecpy = new double [D];
			memcpy(thetaprimecpy, thetaprime, sz);
			double *gradprimecpy = new double [D];
			memcpy(gradprimecpy, gradprime, sz);
			double logpprimecpy = *logpprime;
			double nprimecpy = *nprime;
			bool sprimecpy = *sprime;
			double alphaprimecpy = *alphaprime;
			double nalphaprimecpy = *nalphaprime;
//			if (v == -1)
			if (v == false) {
//				[thetaminus, rminus, gradminus, ~, ~, ~, thetaprime2, gradprime2, logpprime2, nprime2, sprime2, alphaprime2, nalphaprime2] = ...
//					build_tree(thetaminus, rminus, gradminus, logu, v, j-1, epsilon, f, joint0);
				build_tree(thetaminusout, rminusout, gradminusout, logu, v, j-1, epsilon, f, joint0, D, generator, uni01, 
						   thetaminusout, rminusout, gradminusout, NULL, NULL, NULL, thetaprimemat, rprime, gradprime, 
						   logpprime, nprime, sprime, alphaprime, nalphaprime);
//			else
			} else {
//				[~, ~, ~, thetaplus, rplus, gradplus, thetaprime2, gradprime2, logpprime2, nprime2, sprime2, alphaprime2, nalphaprime2] = ...
//					build_tree(thetaplus, rplus, gradplus, logu, v, j-1, epsilon, f, joint0);
				build_tree(thetaplusout, rplusout, gradplusout, logu, v, j-1, epsilon, f, joint0, D, generator, uni01, 
						   NULL, NULL, NULL, thetaplusout, rplusout, gradplusout, thetaprimemat, rprime, gradprime, 
						   logpprime, nprime, sprime, alphaprime, nalphaprime);
//			end
			}
//			if (rand() < nprime2 / (nprime + nprime2))
			if (uni01(generator) < *nprime / (nprimecpy + *nprime)) {
//				thetaprime = thetaprime2;
//				gradprime = gradprime2;
//				logpprime = logpprime2;
			}
//			end
			else {
				memcpy(thetaprime, thetaprimecpy, sz);
				memcpy(gradprime, gradprimecpy, sz);
				*logpprime = logpprimecpy;
			}
//			nprime = nprime + nprime2;
//			sprime = sprime && sprime2 && stop_criterion(thetaminus, thetaplus, rminus, rplus);
//			alphaprime = alphaprime + alphaprime2;
//			nalphaprime = nalphaprime + nalphaprime2;
			*nprime += nprimecpy;
			*sprime = sprimecpy && *sprime && stop_criterion(thetaminusout, thetaplusout, rminusout, rplusout, D);
			*alphaprime += alphaprimecpy;
			*nalphaprime += nalphaprimecpy;
			
			delete [] gradprimecpy;
			delete [] thetaprimecpy;
//		end
		}
		
		if (thetaminus) memcpy(thetaminus, thetaminusout, sz);
		if (rminus) memcpy(rminus, rminusout, sz);
		if (gradminus) memcpy(gradminus, gradminusout, sz);
		if (thetaplus) memcpy(thetaplus, thetaplusout, sz);
		if (rplus) memcpy(rplus, rplusout, sz);
		if (gradplus) memcpy(gradplus, gradplusout, sz);
		delete [] thetaminusout;
		delete [] rminusout;
		delete [] gradminusout;
		delete [] thetaplusout;
		delete [] rplusout;
		delete [] gradplusout;
//	end
	}
//end
}
Beispiel #11
0
main()
{
    double dt, dtcoef;
    double tmax;
    double dtout;
    double time, tout;
    VECT x, v;
    VECT newx, newv;
    scanf("%le%le%le", &dtcoef, &tmax, &dtout);
    scanf("%le%le%le%le", &(x.x), &(x.y), &(v.x), &(v.y));
    printf("dtcoef, tmax, dtout = %e %e %e\n", dtcoef, tmax, dtout);
    printf("x, v = %e %e %e %e\n", (x.x), (x.y), (v.x), (v.y));
    time=0;
    tout = dtout;
    printenergy(x, v, time);
    while (time < tmax){
	double newdt, dt0;
	int i;
	dt = timescale(x, v)*dtcoef;
	dt0=dt;
#ifdef SIMPLE_SYMMETRIC	
	for (i=0;i<5; i++){
	    leapfrog(x,v, &newx, &newv, dt);
	    newdt=timescale(newx, newv)*dtcoef;
	    dt = 0.5*(dt0+newdt);
	}
#endif
#ifdef CORRECTED_BLOCKSTEP	
        dt=force2(dt0);
	if (fmod(time, dt*2)== 0.0) dt*=2;
	for (i=0;i<5; i++){
	    leapfrog(x,v, &newx, &newv, dt);
	    newdt=timescale(newx, newv)*dtcoef;
	    if (dt > 0.5*(dt0+newdt)) dt *= 0.5;
	}
#endif
#ifdef SIMPLE_BLOCKSTEP
#define NSYM 5	
	dt = force2(dt);
	for (i=0;i<NSYM; i++){
	    leapfrog(x,v, &newx, &newv, dt);
	    newdt=timescale(newx, newv)*dtcoef;
	    if (i < NSYM-1){
		dt = force2(0.5*(dt0+newdt));
	    }
	}
#endif
#ifdef MIN_BLOCKSTEP
#define NSYM 5
	{
	    double steps[NSYM];
	    dt = force2(dt);
	    for (i=0;i<NSYM; i++){
		leapfrog(x,v, &newx, &newv, dt);
		newdt=timescale(newx, newv)*dtcoef;
		if (i < NSYM-1){
		    steps[i] = force2(0.5*(dt0+newdt));
		    if (i < NSYM-2) {
			dt = steps[i];
		    }else{
			dt = (steps[i]>steps[i-1])? steps[i-1]:steps[i];
		    }
		}
	    }
	}
#endif
	
	time += dt;
	x=newx;
	v=newv;
	if (time >= tout){
	    printv(x, "x");
	    printv(v, "v");
	    printenergy(x, v, time);
	    tout += dtout;
	}
    }
}
Beispiel #12
0
/**
 * main program
 */
int main (int argc, char** argv)
{
  /* hold positions, velocities, masses, and accelerations for the bodies */
  double3 *x;
  double3 *v;
  double *m;
  double3 *a;
  /* temporary buffer given to leapfrog() so it can store the old acceleration
     values there */
  double3 *temp;
  /* loop counter */
  int i;
  /* count the time steps done */
  int k = 0;
  /* base name for the output files */
  char base[]="test1";
  /* buffer to construct the whole output filename in */
  char name[256];
  /* handle for the output file */
  FILE *file;
  /* accumulated simulation time and time step size.  These will be modified
     when reading initial values from a file */
  double t = 0, dt = 1E-3;
  /* for measuring the elapsed time and calculating the MFLOP rate */
  double start,stop,elapsed,flop;
  /* number of bodies (read from commandline) */
  int n;
  /* number of time steps to do (read from commandline) */
  int timesteps;
  /* when to measure MFLOP rate and write output files: every mod time steps
     (read from commandline) */
  int mod;
  int B;
  /**
   * parse commandline arguments
   */
  if (argc!=5) {
    printf("usage: nbody_vanilla <nbodies> <timesteps> <every> <Blocksize>\n");
    return 1;
  }
  sscanf(argv[1],"%d",&n);
  sscanf(argv[2],"%d",&timesteps);
  sscanf(argv[3],"%d",&mod);
  sscanf(argv[4],"%d",&B);

#if 0
  /* get initial value from a data file */
  file = fopen("plummer10000.vtk","r");
  if (file==NULL) {
    printf("could not open file --- aborting\n");
    return 1;
  }
  /* peek into the file to find out the number of bodies */
  n = get_vtk_numbodies(file);
  rewind(file);
  /* allocate memory accordingly */
  x = calloc(n,sizeof(double3));
  v = calloc(n,sizeof(double3));
  m = calloc(n,sizeof(double));
  /* read everything */
  read_vtk_file_double(file,n,x,v,m,&t,&dt);
  fclose(file);
  printf("loaded %d bodies\n",n);
#else
  /* get initial values from one of the generator functions */
  x = calloc(n,sizeof(double3));
  v = calloc(n,sizeof(double3));
  m = calloc(n,sizeof(double));
  plummer(n,17,x,v,m);
#endif

  /**
   * allocate and initialise the acceleration and the buffer for leapfrog
   */
  a = calloc(n,sizeof(double3));
  for (i=0; i<n; i++)
    a[i][0] = a[i][1] = a[i][2] = 0.0;
  acceleration(n,x,m,a,B);
  temp = calloc(n,sizeof(double3));

  /* write out the initial values */
  sprintf(name,"%s_%06d.vtk",base,k/mod);
//  printf("writing %s \n",name);
  file = fopen(name,"w");
  write_vtk_file_double(file,n,x,v,m,t,dt);
  fclose(file);

  /* start the time measurement */
  start = get_time();
  for (k=1; k<timesteps; k++) {
    /* do one timestep and increment elapsed simulated time */
    leapfrog(n,dt,x,v,m,a,temp);
    t += dt;
    if (k%mod==0) {
      /* write statistics */
      stop = get_time();
      elapsed = stop-start;
      /* 13*n*(n-1)+24*n+3 FLOP from leaprog(), 1 from the t+=dt above */
      flop = mod*(13.0*n*(n-1.0)+24.0*n+4.0);
//      printf("%g seconds for %g ops = %g MFLOPS\n",
      printf("%g\n",flop/elapsed/1E6);

      /* write output file */
      sprintf(name,"%s_%06d.vtk",base,k/mod);
//      printf("writing %s \n",name);
      file = fopen(name,"w");
      write_vtk_file_double(file,n,x,v,m,t,dt);
      fclose(file);

      /* restart the timer */
      start = get_time();
    }
  }

  /* Don't bother freeing the allocated buffers since the program is going to
     end and the operating system will reclaim all of its memory anyway */

  return 0;
}