/** * 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?"); } }
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; }
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; }
int main(void){ int p; lospol(); for(p=0;p<20000;p++){ leapfrog(p); } printhist(); }
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); } }
//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; }
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); } }
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); }
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
//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 }
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; } } }
/** * 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",×teps); 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; }