コード例 #1
0
ファイル: diff_equation.c プロジェクト: slitvinov/BD_BOX
INT compute_hydro_IGT_second_phase( DOUBLE* _E )
{
    INT i;

    compute_r( D ); /* in Rf0 random move */

    if ( !vel_grad_tensor )
    {
        for ( i = 0; i < size; ++i )
        {
            coord[ i * DIMS1 ] += Rf0[ i * DIMS0 ] + Rs[0][ i * DIMS0 ];
            coord[ i * DIMS1 + 1] += Rf0[ i * DIMS0 + 1] + Rs[0][ i * DIMS0 + 1];
            coord[ i * DIMS1 + 2] += Rf0[ i * DIMS0 + 2] + Rs[0][ i * DIMS0 + 2];
            trans_to_box( coord + DIMS1 * i );
        }
    }
    else
    {
        for ( i = 0; i < size; ++i )
        {
            coord[ i * DIMS1 ] += Rf0[ i * DIMS0 ] + Rs[0][ i * DIMS0 ] + 0.5 * FS[ i * DIMS1 ];
            coord[ i * DIMS1 + 1] += Rf0[ i * DIMS0 + 1] + Rs[0][ i * DIMS0 + 1] + 0.5 * FS[ i * DIMS1 + 1];
            coord[ i * DIMS1 + 2] += Rf0[ i * DIMS0 + 2] + Rs[0][ i * DIMS0 + 2] + 0.5 * FS[ i * DIMS1 + 2];
            trans_to_box( coord + DIMS1 * i );
        }
    }
    return compute_forces( _E, curr_time + curr_dt ) << 1;
}
コード例 #2
0
ファイル: md.c プロジェクト: SahanGH/psi4public
void sim_md(struct state *state)
{
	msg("MOLECULAR DYNAMICS JOB\n\n\n");

	struct md *md = md_create(state);

	if (cfg_get_bool(state->cfg, "velocitize"))
		velocitize(md);

	remove_system_drift(md);
	compute_forces(md);

	msg("    INITIAL STATE\n\n");
	print_status(md);

	for (int i = 1; i <= cfg_get_int(state->cfg, "max_steps"); i++) {
		md->update_step(md);

		if (i % cfg_get_int(state->cfg, "print_step") == 0) {
			msg("    STATE AFTER %d STEPS\n\n", i);
			print_status(md);
		}
	}

	md_shutdown(md);

	msg("MOLECULAR DYNAMICS JOB COMPLETED SUCCESSFULLY\n");
}
コード例 #3
0
void Mass_spring_viewer::time_integration(float dt)
{
    switch (integration_)
    {
        case Euler:
        {
            /** \todo (Part 1) Implement Euler integration scheme
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */
            compute_forces();
            
            
            for (unsigned int i=0; i<body_.particles.size(); ++i){
               Particle *p = &body_.particles.at(i);
               
               //update position
               p->position = p->position + dt*p->velocity;
               
               //calculate the new acceleration using newton's second law
               p->acceleration = p->force/p->mass;
               
               p->velocity = p->velocity + dt*p->acceleration;
            }
            
            break;
        }

        case Midpoint:
        {
            /** \todo (Part 2) Implement the Midpoint time integration scheme
             \li The Particle class has variables position_t and velocity_t to store current values
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */

            break;
        }


        case Verlet:
        {
            /** \todo (Part 2) Implement the Verlet time integration scheme
             \li The Particle class has a variable acceleration to remember the previous values
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */

            break;
        }
    }


    // impulse-based collision handling
    if (collisions_ == Impulse_based)
    {
        impulse_based_collisions();
    }


    glutPostRedisplay();
}
コード例 #4
0
ファイル: diff_equation.c プロジェクト: slitvinov/BD_BOX
INT compute_hydro_IGT( DOUBLE* _E )
{
    INT i;
    DOUBLE* tmp_coord;

    compute_hydro_ermak( Rf0 ); /* in Rf determistic move, Rf0 coord for predictor step */

    tmp_coord = coord;
    coord = Rf0;

    if ( compute_forces( NULL, curr_time + curr_dt ) )
    {
        coord = tmp_coord;
        return 1;
    }

    compute_Rf( Rs, (hydro == DIFF_CHOLESKY) ? Ds : D );
    coord = tmp_coord;

    for ( i = 0; i < size * DIMS0; ++i )
    {
        Rf0[i] = 0.5 * (Rf[0][i] + Rs[0][i]); /*determistic move*/
    }

    while ( hydro )
    {
        INT LD = size*DIMS0;
#if USE_MPI
        if ( hydro == DIFF_CHOLESKY )
        {
            sum_tensors_cholesky_mpi( );
            break;
        }
#endif
#ifdef _OPENMP
#pragma omp parallel for schedule( dynamic )
#endif
        for ( i = 0; i < size; ++i )
        {
            INT j, k, l;
            for ( j = 0; j < 3; ++j )
            {
                for ( k = g_id; k < i; k += g_numprocs )
                {
                    for ( l = 0; l < 3; ++l )
                    {
                        D[ (i * DIMS0 + j) * LD + k * DIMS0 + l ] =
                            (D [ (i * DIMS0 + j) * LD + k * DIMS0 + l ] +
                            Ds[ (i * DIMS0 + j) * LD + k * DIMS0 + l ]) / 2;
                    }
                }
            }
        }
        break; /*only once*/
    }
    curr_iter++;
    return compute_hydro_IGT_second_phase( _E );
}
コード例 #5
0
void Mass_spring_viewer::time_integration(float dt)
{
    switch (integration_)
    {
        case Euler:
        {
            /** \todo (Part 1) Implement Euler integration scheme
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */

            compute_forces();

            for(unsigned int i = 0; i < body_.particles.size(); i++)
            {
                body_.particles[i].velocity += (dt/body_.particles[i].mass)*body_.particles[i].force;
                body_.particles[i].position += dt*body_.particles[i].velocity;
            }

            break;


            break;
        }

        case Midpoint:
        {
            /** \todo (Part 2) Implement the Midpoint time integration scheme
             \li The Particle class has variables position_t and velocity_t to store current values
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */

            break;
        }


        case Verlet:
        {
            /** \todo (Part 2) Implement the Verlet time integration scheme
             \li The Particle class has a variable acceleration to remember the previous values
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */

            break;
        }
    }


    // impulse-based collision handling
    if (collisions_ == Impulse_based)
    {
        impulse_based_collisions();
    }


    glutPostRedisplay();
}
コード例 #6
0
void propagate_nuclear(double dt,Nuclear* mol,Electronic* el,Hamiltonian* ham,Thermostat* therm, int opt){
/**
  \brief One step of Velocity verlet algorithm coupled to nuclear Thermostat - for NVT calculations
  !!!  IMPORTANT: Presently, this is only a template - the thermostat part is only outlined - need to test this first !!!

  \param[in] Integration time step
  \param[in,out] mol Describes the nuclear DOF. Changes during the integration.
  \param[in] el Describes electronic DOF. Does not change during the integration.
  \param[in,out] ham Is the Hamiltonian object that works as a functor (takes care of all calculations of given type) -its internal variables
  are changed during the compuations
  \param[in] therm The pointer to a Thermostat object, which contains the information about thermal bath state
  \param[in] opt Option for selecting the way to describe the electron-nuclear interaction: = 0 - Ehrenfest (mean-field, MF), =1 -
  (fewest switched surface hopping, FSSH)

*/

  int i;

  // Propagate momenta and positions of all nuclei
//  mol->P[i] *= exp(-therm->gamma*0.25*dt);
//  mol->P[i] += therm->ksi() * 0.5*dt;
//  mol->P[i] *= exp(-therm->gamma*0.25*dt);


  // exp(iL_q*dt)*exp(iL_p*dt/2)
  mol->propagate_p(0.5*dt);
  mol->propagate_q(dt);

  // Update Hamiltonian
  ham->set_q(mol->q);  ham->compute();  

  // Update forces and potential energy
  compute_potential_energy(mol, el, ham, opt);
  compute_forces(mol, el, ham, opt);


  // Propagate momenta of all nucleii
  // operator exp(iL_p*dt/2)
  mol->propagate_p(0.5*dt);

  // Propagate momenta and positions of all nuclei
//  mol->P[i] *= exp(-therm->gamma*0.25*dt);
//  mol->P[i] += therm->ksi() * 0.5*dt;
//  mol->P[i] *= exp(-therm->gamma*0.25*dt);



}// propagate_nuclear
コード例 #7
0
void propagate_nuclear(double dt,Nuclear* mol,Electronic* el,Hamiltonian* ham,int opt){
/**
  \brief One step of Velocity verlet algorithm for nuclear DOF
  \param[in] Integration time step
  \param[in,out] mol Describes the nuclear DOF. Changes during the integration.
  \param[in] el Describes electronic DOF. Does not change during the integration.
  \param[in,out] ham Is the Hamiltonian object that works as a functor (takes care of all calculations of given type) -its internal variables
  are changed during the compuations
  \param[in] opt Option for selecting the way to describe the electron-nuclear interaction: = 0 - Ehrenfest (mean-field, MF), =1 -
  (fewest switched surface hopping, FSSH)

*/


  int i;
  vector<double> v_(mol->nnucl); 

  // Propagate momenta and positions of all nuclei
  // exp(iL_q*dt)*exp(iL_p*dt/2)
  mol->propagate_p(0.5*dt);
  mol->propagate_q(dt);

  // Update Hamiltonian
  ham->set_q(mol->q);
  for(i=0;i<mol->nnucl;i++){ v_[i] = mol->p[i]/mol->mass[i]; }  ham->set_v(v_);
  ham->compute();  

  // Update forces and potential energy
  compute_potential_energy(mol, el, ham, opt);
  compute_forces(mol, el, ham, opt);


  // Propagate momenta of all nucleii
  // operator exp(iL_p*dt/2)
  mol->propagate_p(0.5*dt);


//  ham->set_q(mol->q);
  for(i=0;i<mol->nnucl;i++){ v_[i] = mol->p[i]/mol->mass[i]; }  ham->set_v(v_);
//  ham->compute();  



}// propagate_nuclear
コード例 #8
0
void Rigid_body_viewer::time_integration(float dt)
{
    // compute all forces
    compute_forces();

    /** \todo Implement explicit Euler time integration
     \li update position and orientation
     \li update linear and angular velocities
     \li call update_points() at the end to compute the new particle positions
     */

     body_.linear_velocity += body_.force * dt / body_.mass;
     body_.position += body_.linear_velocity * dt;

     body_.angular_velocity += body_.torque * dt / body_.inertia;
     body_.orientation += body_.angular_velocity * dt;

     body_.update_points();

    // handle collisions
    impulse_based_collisions();
}
コード例 #9
0
ファイル: md.c プロジェクト: SahanGH/psi4public
static void update_step_nve(struct md *md)
{
	double dt = cfg_get_double(md->state->cfg, "time_step");

	for (size_t i = 0; i < md->n_bodies; i++) {
		struct body *body = md->bodies + i;

		body->vel.x += 0.5 * body->force.x * dt / body->mass;
		body->vel.y += 0.5 * body->force.y * dt / body->mass;
		body->vel.z += 0.5 * body->force.z * dt / body->mass;

		body->angmom.x += 0.5 * body->torque.x * dt;
		body->angmom.y += 0.5 * body->torque.y * dt;
		body->angmom.z += 0.5 * body->torque.z * dt;

		body->pos.x += body->vel.x * dt;
		body->pos.y += body->vel.y * dt;
		body->pos.z += body->vel.z * dt;

		rotate_body(body, dt);
	}

	compute_forces(md);

	for (size_t i = 0; i < md->n_bodies; i++) {
		struct body *body = md->bodies + i;

		body->vel.x += 0.5 * body->force.x * dt / body->mass;
		body->vel.y += 0.5 * body->force.y * dt / body->mass;
		body->vel.z += 0.5 * body->force.z * dt / body->mass;

		body->angmom.x += 0.5 * body->torque.x * dt;
		body->angmom.y += 0.5 * body->torque.y * dt;
		body->angmom.z += 0.5 * body->torque.z * dt;
	}
}
コード例 #10
0
ファイル: md_opt.c プロジェクト: bragilee/project
int main(int argc, char** argv)
{
  //printf("%f\n",GRID_NUM);
  struct timespec diff(struct timespec start, struct timespec end);
  struct timespec time1, time2;
  struct timespec time_stamp;


  int npart,i,j,Num;

  params param;
  mols mol;
  adjacent adj;

  param.npart = N_BODY_NUM;
  param.dt = DT;
  param.eps_lj = EPS;
  param.sig_lj = SIG;

  mol.x = malloc(2*param.npart * sizeof(float));
  mol.v = malloc(2*param.npart * sizeof(float));
  mol.a = malloc(2*param.npart * sizeof(float));
  mol.F = malloc(2*param.npart * sizeof(float));
#if (NEAREST)
  double Blength = BLOCK_LENGTH(GRID_NUM,BOX_SIZE);
  printf("Blength: %lf\n",Blength);
  Num = EST_NUM(GRID_NUM,N_BODY_NUM);
  Num = 4*Num;
  if(!Num)
  {
     Num = 4;
  }
  
  if(N_BODY_NUM < Num)
  {
    Num = N_BODY_NUM;
  }

  adj.n = malloc(sizeof(int) * GRID_NUM * GRID_NUM * Num);
  memset(adj.n,-1,sizeof(int) * GRID_NUM * GRID_NUM *  Num);
  printf("Num: %d\n",Num);
#endif

  npart = init_particles(param.npart, mol.x , mol.v, &param);
  if(npart < param.npart)
  {
    fprintf(stderr, "Could not generate %d particles, Trying %d particles instead\n",param.npart,npart);
    param.npart = npart;
  }
  else
  {
    fprintf(stdout,"Generated %d particles\n",param.npart);
  }

  init_particles_va( param.npart, mol.v,mol.a, &param);

#if(NEAREST)
  printf("Before gridSort\n");
  gridSort(npart, GRID_NUM, Num, adj.n, mol.x);
  printf("After gridSort\n");
#endif

  /*for(i=0;i<npart;i++)
    printf("myBlockNum: %d\n",getMyBlock(param.npart,2*i, adj.n, Num/2));

    for(i=0; i < param.npart; i++)
    {
    printf("nBody-Num: %d Posx: %f Velx: %f Accx: %f Forcex: %f\n",i,
    mol.x[2*i],mol.v[2*i],mol.a[2*i],mol.F[2*i]);
    printf("nBody-Num: %d Posy: %f Vely: %f Accy: %f Forcey: %f\n",i,
    mol.x[2*i+1],mol.v[2*i+1],mol.a[2*i+1],mol.F[2*i+1]);
    }
    */

#if(LINUX)

  clock_gettime(CLOCK_REALTIME, &time1);

#endif
#if(NEAREST)
  compute_forces_nearby(param.npart, adj.n, mol.x, mol.F, GRID_NUM, Num);

#elif(OPT)  
  compute_forces(param.npart,mol.x,mol.F);
#else
    compute_forces_naive(param.npart,mol.x,mol.F);

#endif
  printf("After First ComputeForces\n");
  for(i=0;i<ITERS;i++)
  {
#if(NEAREST)
    gridSort(npart, GRID_NUM, Num, adj.n, mol.x);		    // Added in the gridSort function for each iteration
#endif
    verletInt1(param.npart,param.dt , mol.x, mol.v,mol.a);
    box_reflect(param.npart,mol.x,mol.v,mol.a );
#if(NEAREST)
    compute_forces_nearby(param.npart, adj.n, mol.x, mol.F, GRID_NUM, Num);
#elif(OPT)
    compute_forces(param.npart,mol.x,mol.F);
#else
    compute_forces_naive(param.npart,mol.x,mol.F);
#endif
    verletInt2(param.npart,param.dt, mol.x, mol.v, mol.a);
    memset(mol.F, 0 , 2*param.npart * sizeof(float));
  }

#if(LINUX)

  clock_gettime(CLOCK_REALTIME, &time2);

#endif

  /*
     for(i=0; i < param.npart; i++)
     {
     printf("nBody-Num: %d Posx: %f Velx: %f Accx: %f Forcex: %f\n",i,
     mol.x[2*i],mol.v[2*i],mol.a[2*i],mol.F[2*i]);
     printf("nBody-Num: %d Posy: %f Vely: %f Accy: %f Forcey: %f\n",i,
     mol.x[2*i+1],mol.v[2*i+1],mol.a[2*i+1],mol.F[2*i+1]);
     }
     */

#if(LINUX)

  double blength = BLOCK_LENGTH(GRID_NUM,BOX_SIZE);
  printf("Boxsize: %lf,Blocksize: %lf,MaxBodiesPerBlock: %d\n",BOX_SIZE,blength, maxNumPartPerBlock(blength,SIG));
  time_stamp = diff(time1,time2);
  printf("Execution time: %lf\n",(double)((time_stamp.tv_sec + (time_stamp.tv_nsec/1.0e9))));

#else

  printf("Boxsize: %lf,BlockNum: %lf,MaxBodiesPerBlock: %d\n",BOX_SIZE,GRID_NUM, maxNumPartPerBlock(GRID_NUM,SIG));

#endif

  /*        // test statements for the grid allocation
            int count =0;
            for(i=0;i<GRID_NUM*GRID_NUM*Num/2;i++)
            {
            if(adj.n[i]!=-1)
            {
            count++;
            }
            }
            printf("%d\n",count);

*/
#if(NEAREST)
  free(adj.n);
#endif
  free(mol.x);
  free(mol.v);
  free(mol.a);
  free(mol.F);
  printf("Done\n");

  return 0;
}
コード例 #11
0
ファイル: md.c プロジェクト: SahanGH/psi4public
/*
 * Reference
 *
 * Simone Melchionna, Giovanni Ciccotti, Brad Lee Holian
 *
 * Hoover NPT dynamics for systems varying in shape and size
 *
 * Mol. Phys. 78, 533 (1993)
 */
static void update_step_npt(struct md *md)
{
	struct npt_data *data = (struct npt_data *)md->data;

	double dt = cfg_get_double(md->state->cfg, "time_step");
	double t_tau = cfg_get_double(md->state->cfg, "thermostat_tau");
	double t_target = cfg_get_double(md->state->cfg, "temperature");
	double p_tau = cfg_get_double(md->state->cfg, "barostat_tau");
	double p_target = cfg_get_double(md->state->cfg, "pressure");

	double t_tau2 = t_tau * t_tau;
	double p_tau2 = p_tau * p_tau;
	double kbt = BOLTZMANN * t_target;

	double t0 = get_temperature(md);
	double p0 = get_pressure(md);
	double v0 = get_volume(md);

	for (size_t i = 0; i < md->n_bodies; i++) {
		struct body *body = md->bodies + i;

		body->vel.x += 0.5 * dt * (body->force.x / body->mass -
					body->vel.x * (data->chi + data->eta));
		body->vel.y += 0.5 * dt * (body->force.y / body->mass -
					body->vel.y * (data->chi + data->eta));
		body->vel.z += 0.5 * dt * (body->force.z / body->mass -
					body->vel.z * (data->chi + data->eta));

		body->angmom.x += 0.5 * dt * (body->torque.x -
						body->angmom.x * data->chi);
		body->angmom.y += 0.5 * dt * (body->torque.y -
						body->angmom.y * data->chi);
		body->angmom.z += 0.5 * dt * (body->torque.z -
						body->angmom.z * data->chi);

		rotate_body(body, dt);
	}

	data->chi += 0.5 * dt * (t0 / t_target - 1.0) / t_tau2;
	data->chi_dt += 0.5 * dt * data->chi;
	data->eta += 0.5 * dt * v0 * (p0 - p_target) / md->n_bodies / kbt / p_tau2;

	vec_t com = get_system_com(md);
	vec_t pos_init[md->n_bodies];

	for (size_t i = 0; i < md->n_bodies; i++)
		pos_init[i] = md->bodies[i].pos;

	for (size_t iter = 1; iter <= MAX_ITER; iter++) {
		bool done = true;

		for (size_t i = 0; i < md->n_bodies; i++) {
			struct body *body = md->bodies + i;
			vec_t pos = wrap(md, &body->pos);

			vec_t v = {
				data->eta * (pos.x - com.x),
				data->eta * (pos.y - com.y),
				data->eta * (pos.z - com.z)
			};

			vec_t new_pos = {
				pos_init[i].x + dt * (body->vel.x + v.x),
				pos_init[i].y + dt * (body->vel.y + v.y),
				pos_init[i].z + dt * (body->vel.z + v.z)
			};

			done = done && vec_dist(&body->pos, &new_pos) < EPSILON;
			body->pos = new_pos;
		}

		if (done)
			break;

		if (iter == MAX_ITER)
			msg("WARNING: NPT UPDATE DID NOT CONVERGE\n\n");
	}

	vec_scale(&md->box, exp(dt * data->eta));
	check_fail(efp_set_periodic_box(md->state->efp, md->box.x, md->box.y, md->box.z));

	compute_forces(md);

	double chi_init = data->chi, eta_init = data->eta;
	vec_t angmom_init[md->n_bodies], vel_init[md->n_bodies];

	for (size_t i = 0; i < md->n_bodies; i++) {
		angmom_init[i] = md->bodies[i].angmom;
		vel_init[i] = md->bodies[i].vel;
	}

	for (size_t iter = 1; iter <= MAX_ITER; iter++) {
		double chi_prev = data->chi;
		double eta_prev = data->eta;
		double t_cur = get_temperature(md);
		double p_cur = get_pressure(md);
		double v_cur = get_volume(md);

		data->chi = chi_init + 0.5 * dt * (t_cur / t_target - 1.0) / t_tau2;
		data->eta = eta_init + 0.5 * dt * v_cur * (p_cur - p_target) /
							md->n_bodies / kbt / p_tau2;

		for (size_t i = 0; i < md->n_bodies; i++) {
			struct body *body = md->bodies + i;

			body->vel.x = vel_init[i].x + 0.5 * dt *
				(body->force.x / body->mass -
					vel_init[i].x * (data->chi + data->eta));
			body->vel.y = vel_init[i].y + 0.5 * dt *
				(body->force.y / body->mass -
					vel_init[i].y * (data->chi + data->eta));
			body->vel.z = vel_init[i].z + 0.5 * dt *
				(body->force.z / body->mass -
					vel_init[i].z * (data->chi + data->eta));

			body->angmom.x = angmom_init[i].x + 0.5 * dt *
				(body->torque.x - angmom_init[i].x * data->chi);
			body->angmom.y = angmom_init[i].y + 0.5 * dt *
				(body->torque.y - angmom_init[i].y * data->chi);
			body->angmom.z = angmom_init[i].z + 0.5 * dt *
				(body->torque.z - angmom_init[i].z * data->chi);
		}

		if (fabs(data->chi - chi_prev) < EPSILON &&
		    fabs(data->eta - eta_prev) < EPSILON)
			break;

		if (iter == MAX_ITER)
			msg("WARNING: NPT UPDATE DID NOT CONVERGE\n\n");
	}

	data->chi_dt += 0.5 * dt * data->chi;
}
コード例 #12
0
ファイル: md.c プロジェクト: SahanGH/psi4public
/*
 * NVT with Nose-Hoover thermostat:
 *
 * William G. Hoover
 *
 * Canonical dynamics: Equilibrium phase-space distributions
 *
 * Phys. Rev. A 31, 1695 (1985)
 */
static void update_step_nvt(struct md *md)
{
	struct nvt_data *data = (struct nvt_data *)md->data;

	double dt = cfg_get_double(md->state->cfg, "time_step");
	double target = cfg_get_double(md->state->cfg, "temperature");
	double tau = cfg_get_double(md->state->cfg, "thermostat_tau");

	double t0 = get_temperature(md);

	for (size_t i = 0; i < md->n_bodies; i++) {
		struct body *body = md->bodies + i;

		body->vel.x += 0.5 * dt * (body->force.x / body->mass -
					body->vel.x * data->chi);
		body->vel.y += 0.5 * dt * (body->force.y / body->mass -
					body->vel.y * data->chi);
		body->vel.z += 0.5 * dt * (body->force.z / body->mass -
					body->vel.z * data->chi);

		body->angmom.x += 0.5 * dt * (body->torque.x -
					body->angmom.x * data->chi);
		body->angmom.y += 0.5 * dt * (body->torque.y -
					body->angmom.y * data->chi);
		body->angmom.z += 0.5 * dt * (body->torque.z -
					body->angmom.z * data->chi);

		body->pos.x += body->vel.x * dt;
		body->pos.y += body->vel.y * dt;
		body->pos.z += body->vel.z * dt;

		rotate_body(body, dt);
	}

	data->chi += 0.5 * dt * (t0 / target - 1.0) / tau / tau;
	data->chi_dt += 0.5 * dt * data->chi;

	compute_forces(md);

	double chi_init = data->chi;
	vec_t angmom_init[md->n_bodies], vel_init[md->n_bodies];

	for (size_t i = 0; i < md->n_bodies; i++) {
		angmom_init[i] = md->bodies[i].angmom;
		vel_init[i] = md->bodies[i].vel;
	}

	for (size_t iter = 1; iter <= MAX_ITER; iter++) {
		double chi_prev = data->chi;
		double ratio = get_temperature(md) / target;

		data->chi = chi_init + 0.5 * dt * (ratio - 1.0) / tau / tau;

		for (size_t i = 0; i < md->n_bodies; i++) {
			struct body *body = md->bodies + i;

			body->vel.x = vel_init[i].x + 0.5 * dt *
				(body->force.x / body->mass - vel_init[i].x * data->chi);
			body->vel.y = vel_init[i].y + 0.5 * dt *
				(body->force.y / body->mass - vel_init[i].y * data->chi);
			body->vel.z = vel_init[i].z + 0.5 * dt *
				(body->force.z / body->mass - vel_init[i].z * data->chi);

			body->angmom.x = angmom_init[i].x + 0.5 * dt *
				(body->torque.x - angmom_init[i].x * data->chi);
			body->angmom.y = angmom_init[i].y + 0.5 * dt *
				(body->torque.y - angmom_init[i].y * data->chi);
			body->angmom.z = angmom_init[i].z + 0.5 * dt *
				(body->torque.z - angmom_init[i].z * data->chi);
		}

		if (fabs(data->chi - chi_prev) < EPSILON)
			break;

		if (iter == MAX_ITER)
			msg("WARNING: NVT UPDATE DID NOT CONVERGE\n\n");
	}

	data->chi_dt += 0.5 * dt * data->chi;
}
コード例 #13
0
void State::run_md(Nuclear& mol, Electronic& el, Hamiltonian& ham){

  if(md==NULL) { std::cout<<"Error: MD parameters have not been defined\n"; exit(1);}
  if(!is_md_initialized){    std::cout<<"Error: Need to call init_md() first. MD is not initialized\n"; exit(2);   }

  int is_thermostat, is_barostat;
  is_thermostat = ((thermostat!=NULL) && ((md->ensemble=="NVT")||(md->ensemble=="NPT")||(md->ensemble=="NPT_FLEX")));
  is_barostat   = ((barostat!=NULL) && ((md->ensemble=="NPT")||(md->ensemble=="NPT_FLEX")||(md->ensemble=="NPH")||(md->ensemble=="NPH_FLEX")));

  double dt = md->dt;
  double dt_half = 0.5*md->dt;
  double Nf = syst->Nf_t + syst->Nf_r;
  int Nf_b = 0;
  if(is_barostat) {Nf_b = barostat->get_Nf_b();}
  double scl,sc3,sc4,ksi_r;
  MATRIX3x3 S,I,sc1,sc2;


  while(md->curr_step<md->max_step){

    // Operator NHCB(dt/2)
    if(is_thermostat){
      double ekin_baro = 0.0;
      if(is_barostat){  ekin_baro = barostat->ekin_baro(); }
      thermostat->update_thermostat_forces(syst->ekin_tr(),syst->ekin_rot(),ekin_baro);
      thermostat->propagate_nhc(dt_half,syst->ekin_tr(),syst->ekin_rot(),ekin_baro);
    }


    if(is_thermostat){  thermostat->propagate_sPs(dt_half);    }

    //bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
    // Operator B(dt/2)
    if(is_barostat){
      if(md->ensemble=="NPT"||md->ensemble=="NPH"){ barostat->update_barostat_forces(syst->ekin_tr(),syst->ekin_rot(),curr_V,curr_P);   }
      else if(md->ensemble=="NPT_FLEX"||md->ensemble=="NPH_FLEX"){ barostat->update_barostat_forces(syst->ekin_tr(),syst->ekin_rot(),curr_V,curr_P_tens);   }
      scl = 0.0; if(is_thermostat){ scl = thermostat->get_ksi_b();  }
      barostat->propagate_velocity(dt_half,scl);
    }
    //bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb


    double s_var,Ps,dt_half_s,dt_over_s,dt_over_s2;
    s_var = 1.0; Ps = 0.0;
    dt_half_s = dt_half;
    dt_over_s = dt;
    dt_over_s2 = dt;

    if(md->ensemble=="NVT"||md->ensemble=="NPT"||md->ensemble=="NPT_FLEX"||md->ensemble=="NPH"||md->ensemble=="NPH_FLEX"){
      if(is_thermostat){
        s_var = thermostat->get_s_var(); 
        dt_half_s = dt_half*s_var;
        dt_over_s = (dt/s_var);
        dt_over_s2 = (dt_over_s/s_var);
      }
    }

    //aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa    
    // Operator A(dt/2)
    //-------------------- Linear momentum propagation --------------------
    S = 0.0; I.identity();
    if(is_barostat){
      if(Nf_b==9){ S = barostat->ksi_eps + (barostat->ksi_eps.tr()/(barostat->get_Nf_t()/*+barostat->get_Nf_r()*/))*I; }
      else if(Nf_b==1){S = barostat->ksi_eps_iso * I + (3.0*barostat->ksi_eps_iso/(barostat->get_Nf_t()/*+barostat->get_Nf_r()*/))*I; }
    }
    if(is_thermostat){   S = S + thermostat->get_ksi_t() * I;      }
    sc1 = (exp_(S,-dt_half));//.symmetrized();
    sc2 = dt_half*(exp1_(S,-dt_half*0.5));//.symmetrized()*dt_half;

    //------------------- Angular momentum propagation -----------------------    
    if(is_thermostat){ ksi_r = thermostat->get_ksi_r();}else{ ksi_r = 0.0;}
    sc3 = exp(-dt_half*ksi_r);
    sc4 = dt_half*exp(-0.5*dt_half*ksi_r)*sinh_(0.5*dt_half*ksi_r);



    for(int i=0;i<syst->Number_of_fragments;i++){
      RigidBody& top = syst->Fragments[i].Group_RB;
      //-------------------- Linear momentum propagation --------------------
      top.scale_linear_(sc1);
      top.apply_force(sc2);
      //------------------- Angular momentum propagation -----------------------
      top.scale_angular_(sc3);
      top.apply_torque(sc4);       
    }// for i
    

//    if(is_thermostat){
//      thermostat->propagate_Ps(-dt_half*E_pot);
//    }
    //aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    if(is_thermostat){  thermostat->propagate_Ps(-dt_half*E_pot);    }

    //ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
    //ccccccccccccccccccccccccccccccc Core part ccccccccccccccccccccccccccccccccccccc
    sc1.identity();
    sc2.identity();
    sc2 = sc2 * dt;
    if(is_barostat){
      sc1 = (barostat->pos_scale(dt));
      sc2 = dt*barostat->vpos_scale(dt);
    }

    for(i=0;i<syst->Number_of_fragments;i++){
      RigidBody& top = syst->Fragments[i].Group_RB;
      if(is_thermostat){  thermostat->propagate_Ps( 0.5*dt_over_s2*(top.ekin_rot()+top.ekin_tr()) ); }
      double Ps,s_var;
      s_var = 1.0;  if(is_thermostat){ s_var = thermostat->s_var; }
      Ps = 0.0;
      if(md->integrator=="Jacobi")    { top.propagate_exact_rb(dt_over_s); }
      else if(md->integrator=="DLML")  { top.propagate_dlml(dt_over_s,Ps); }
      else if(md->integrator=="Terec") { top.propagate_terec(dt_over_s);}
      else if(md->integrator=="qTerec") { top.propagate_qterec(dt_over_s);}
      else if(md->integrator=="NO_SQUISH"){ top.propagate_no_squish(dt_over_s);}
      else if(md->integrator=="KLN")   { top.propagate_kln(dt_over_s);}
      else if(md->integrator=="Omelyan"){ top.propagate_omelyan(dt_over_s);}

      if(is_thermostat){  thermostat->propagate_Ps( 0.5*dt_over_s2*(top.ekin_rot()+top.ekin_tr()) ); } 
      if(is_barostat) {  
        top.scale_position(sc1); 
        top.shift_position(sc2*top.rb_p*top.rb_iM);
      }
      else{
        top.shift_position(dt_over_s*top.rb_p*top.rb_iM);
      }        

    }// for i - all fragments

    if(is_thermostat){  thermostat->propagate_Ps(dt*( H0 - Nf*boltzmann*thermostat->Temperature*(log(thermostat->s_var)+1.0) ) ); }


    // Update cell shape
    if(is_barostat){ 
      if(syst->is_Box) {
        VECTOR t1_n,t2_n,t3_n; // new
        VECTOR t1_o,t2_o,t3_o; // old

        syst->Box  =  barostat->pos_scale(dt) * syst->Box;
/*
        system->Boxold.get_vectors(t1_o,t2_o,t3_o);
        system->Box.get_vectors(t1_n,t2_n,t3_n);

        // Find minimal heights of old and new boxes
        double h1_n,h2_n,h3_n;
        double h1_o,h2_o,h3_o;
        double V_n, V_o;  // Volume
        double max_n,min_n,max_o,min_o; // maximal and minimal heights new and old

        V_n = fabs(system->Box.Determinant());
        V_o = fabs(system->Boxold.Determinant());
        VECTOR S;
        S.cross(t2_n,t3_n); h1_n = V_n/fabs(S.length());
        S.cross(t3_n,t1_n); h2_n = V_n/fabs(S.length());
        S.cross(t1_n,t2_n); h3_n = V_n/fabs(S.length());
        max_n = (h1_n>=h2_n)?h1_n:h2_n;      min_n = (h1_n<=h2_n)?h1_n:h2_n;
        max_n = (max_n>=h3_n)?max_n:h3_n;    min_n = (min_n<=h3_n)?min_n:h3_n;

        S.cross(t2_o,t3_o); h1_o = V_o/fabs(S.length());
        S.cross(t3_o,t1_o); h2_o = V_o/fabs(S.length());
        S.cross(t1_o,t2_o); h3_o = V_o/fabs(S.length());
        max_o = (h1_o>=h2_o)?h1_o:h2_o;      min_o = (h1_o<=h2_o)?h1_o:h2_o;
        max_o = (max_o>=h3_o)?max_o:h3_o;    min_o = (min_o<=h3_o)?min_o:h3_o;

        int n_max = ceil((12.0+2.0)/min_n)+1;
        int o_max = ceil((12.0+2.0)/min_o)+1;
        n_max = (n_max>=o_max)?n_max:o_max;

        double dt1,dt2;
        dt1 = (max_n - min_o); dt1 = dt1*dt1;
        dt2 = (max_o - min_n); dt2 = dt2*dt2;
        system->dT_2 = 4.0*3.0*n_max*n_max*((dt1>=dt2)?dt1:dt2);
*/
      }
    }

    // Update atomic positions and calculate interactions
    for(i=0;i<syst->Number_of_fragments;i++){ syst->update_atoms_for_fragment(i);  }
    syst->zero_forces_and_torques();

//!!!!!!!!!!!!!!!!1    E_pot = system->energy(); !!!!!!!!!!!!!!!!1
    syst->extract_atomic_q(mol.q); // syst -> mol
//    E_pot = compute_potential_energy(mol, el, ham, 1); //  # 1 - FSSH forces
    E_pot = compute_forces(mol, el, ham, 1); 
    syst->set_atomic_f(mol.f);    // mol -> syst

    // Update rigid-body variables
    syst->update_fragment_forces_and_torques();


    //cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

    
    //aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    // Operator A(dt/2)
    E_kin = 0.0;
    //-------------------- Linear momentum propagation --------------------
    S = 0.0; I.identity();
    if(is_barostat){
      if(Nf_b==9){ S = barostat->ksi_eps + (barostat->ksi_eps.tr()/(barostat->get_Nf_t()/*+barostat->get_Nf_r()*/))*I; }
      else if(Nf_b==1){S = barostat->ksi_eps_iso * I + (3.0*barostat->ksi_eps_iso/(barostat->get_Nf_t()/*+barostat->get_Nf_r()*/))*I; }
    }
    if(is_thermostat){   S = S + thermostat->get_ksi_t() * I;      }
    sc1 = (exp_(S,-dt_half));//.symmetrized();
    sc2 = dt_half*(exp1_(S,-dt_half*0.5));//.symmetrized()*dt_half;

    //------------------- Angular momentum propagation -----------------------
    if(is_thermostat){ ksi_r = thermostat->get_ksi_r();}else{ ksi_r = 0.0;}
    sc3 = exp(-dt_half*ksi_r);
    sc4 = dt_half*exp(-0.5*dt_half*ksi_r)*sinh_(0.5*dt_half*ksi_r);


    for(i=0;i<syst->Number_of_fragments;i++){
      RigidBody& top = syst->Fragments[i].Group_RB;
      //-------------------- Linear momentum propagation --------------------
      top.scale_linear_(sc1);
      top.apply_force(sc2);
      //------------------- Angular momentum propagation -----------------------
      top.scale_angular_(sc3);
      top.apply_torque(sc4);
      E_kin += (top.ekin_rot() + top.ekin_tr());
    }// for i

    //aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    if(is_thermostat){ thermostat->propagate_Ps( -dt_half*E_pot); }
   //------- Update state variables ------------
      curr_P_tens = syst->pressure_tensor();
      curr_P = (curr_P_tens.tr()/3.0);
      curr_V = syst->volume();
//   curr_P_tens = 0.0;
//   curr_P = 0.0;
//   curr_V = 1e+10;
   //-------------------------------------------

    //bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
    // Operator B(dt/2)
    if(is_barostat){
      if(md->ensemble=="NPT"||md->ensemble=="NPH"){ barostat->update_barostat_forces(syst->ekin_tr(),syst->ekin_rot(),curr_V,curr_P);   }
      else if(md->ensemble=="NPT_FLEX"||md->ensemble=="NPH_FLEX"){ barostat->update_barostat_forces(syst->ekin_tr(),syst->ekin_rot(),curr_V,curr_P_tens);   }
      scl = 0.0; if(is_thermostat){ scl = thermostat->get_ksi_b();  }
      barostat->propagate_velocity(dt_half,scl);
    }

    //bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

    if(is_thermostat){thermostat->propagate_sPs(dt_half); }

    // Operator NHCB(dt/2)
    if(is_thermostat){
      double ekin_baro = 0.0;
      if(is_barostat){  ekin_baro = barostat->ekin_baro(); }
      thermostat->update_thermostat_forces(syst->ekin_tr(),syst->ekin_rot(),ekin_baro);
      thermostat->propagate_nhc(dt_half,syst->ekin_tr(),syst->ekin_rot(),ekin_baro);
    }


    if(md->ensemble=="NVE"){ s_var = 1.0;  Ps = 0.0;}
    if(is_thermostat){   E_kin/=(thermostat->s_var*thermostat->s_var); }

    E_kin_tr = syst->ekin_tr();
    E_kin_rot = syst->ekin_rot();
    E_tot = E_kin + E_pot;
//    if(!is_H0){ H0 = E_tot + thermostat->energy(); is_H0 = 1;}

    if(md->ensemble=="NVE"){  H_NP = E_tot; }
    else if(md->ensemble=="NVT"){
      if(is_thermostat){
        if(!is_H0){ H0 = E_tot + thermostat->energy(); is_H0 = 1;}
        if(thermostat->thermostat_type=="Nose-Poincare"){    H_NP = thermostat->s_var*(E_tot + thermostat->energy() - H0);   }
        else if(thermostat->thermostat_type=="Nose-Hoover"){ H_NP = E_tot + thermostat->energy();    }
      }
    }
    else if(md->ensemble=="NPH"||md->ensemble=="NPH_FLEX"){
      if(is_barostat){  H_NP = E_tot + barostat->ekin_baro() + curr_V * barostat->Pressure;   }
    }
    else if(md->ensemble=="NPT" || md->ensemble=="NPT_FLEX"){
      if(is_barostat){   H_NP = E_tot + barostat->ekin_baro() + curr_V * barostat->Pressure;  }
      if(is_thermostat){ H_NP += thermostat->energy();   }
    }

    curr_T = 2.0*E_kin/(Nf*(boltzmann/hartree));

    //------------- Angular velocity --------------
    L_tot = 0.0; 
    P_tot = 0.0;
    for(i=0;i<syst->Number_of_fragments;i++){
      RigidBody& top = syst->Fragments[i].Group_RB;
      VECTOR tmp; tmp.cross(top.rb_cm,top.rb_p);
      L_tot += top.rb_A_I_to_e_T * top.rb_l_e + tmp;
      P_tot += top.rb_p;
    }

    md->curr_step++;
    md->curr_time+=dt;
      
  }// for s
  md->curr_step = 0;
  md->curr_time = 0.0;
}
コード例 #14
0
void State::init_md(Nuclear& mol, Electronic& el, Hamiltonian& ham, Random& rnd){

  //----- Checking type of ensemble and the existence of required variables ------
  int is_thermostat, is_barostat, is_system;
  is_system = (syst!=NULL);
  is_thermostat = (thermostat!=NULL);
  is_barostat   = (barostat!=NULL);
  cout<<"is_system = "<<is_system<<endl;
  cout<<"is_thermostat = "<<is_thermostat<<endl;
  cout<<"is_barostat = "<<is_barostat<<endl;

  int Nf_b = 0;
  if(!is_system){ std::cout<<"Fatal error: No system defined - nothing to simulate\n Exiting now...\n"; exit(1); }

  if(md->ensemble=="NVT"||md->ensemble=="NPT"){
    if(!is_thermostat){ std::cout<<"Error: No Thermostat object were set up. Can not run simulations in "<<md->ensemble<<" ensemble\n"; exit(1);}    
  }
  if(md->ensemble=="NPT"||md->ensemble=="NPH"){
    Nf_b = 1;
    if(!is_barostat){std::cout<<"Error: No Barostat object were set up. Can not run simulations in "<<md->ensemble<<" ensemble\n"; exit(1);}
  }
  if(md->ensemble=="NPT_FLEX"||md->ensemble=="NPH_FLEX"){
    Nf_b = 9;
    if(!is_barostat){std::cout<<"Error: No Barostat object were set up. Can not run simulations in "<<md->ensemble<<" ensemble\n"; exit(1);}
  }
//  if(md->ensemble=="NVE"){is_thermostat = 0; is_barostat = 0; }

  //---------------- Checking combinations -----------------------------------
  if(is_barostat&&is_thermostat){
    if(thermostat->thermostat_type!="Nose-Hoover" && md->ensemble=="NPT"){  
      std::cout<<"Error: Can not use thermostat other than Nose-Hoover for simulations in NPT ensemble\n Exiting now...\n"; exit(1);
    }
  }

  //------ Initialize thermostat and/or barostat if they exist ----------------
  if(is_thermostat){
    thermostat->set_Nf_t(syst->Nf_t); 
    thermostat->set_Nf_r(syst->Nf_r);
    if(is_barostat){  thermostat->set_Nf_b(Nf_b); }
    thermostat->init_nhc();
    syst->init_fragment_velocities(thermostat->Temperature, rnd);
  }
  if(is_barostat){   
    barostat->set_Nf_t(syst->Nf_t);
    barostat->set_Nf_r(syst->Nf_r);
    barostat->set_Nf_b(Nf_b);
    if(is_thermostat){    barostat->init(thermostat->Temperature); }
  }

  //---------------- Initialize system --------------------
  E_kin = 0.0;
  for(int i=0;i<syst->Number_of_fragments;i++){
    RigidBody& top = syst->Fragments[i].Group_RB;
    E_kin += (top.ekin_tr() + top.ekin_rot());
  }
  syst->zero_forces_and_torques();

//!!!!!!!!!!  E_pot = system->energy(); !!!!!!!!!!!!!!!!!
  syst->extract_atomic_q(mol.q); // syst -> mol
  E_pot = compute_potential_energy(mol, el, ham, 1); //  # 1 - FSSH forces
  compute_forces(mol, el, ham, 1); 
  syst->set_atomic_f(mol.f);    // mol -> syst

  syst->update_fragment_forces_and_torques();

  E_tot = E_pot + E_kin;
  H0 = E_tot; 
  H_NP = 0.0;
  if(is_thermostat){  H0 += thermostat->energy();  }
 
  if(md->integrator=="Terec"||md->integrator=="qTerec"){
    for(int i=0;i<syst->Number_of_fragments;i++){
      syst->Fragments[i].Group_RB.initialize_terec(md->terec_exp_size);
    }
  }
  is_md_initialized = 1;

  if(is_thermostat){ thermostat->show_info(); }
  if(is_barostat){  barostat->show_info(); }

}
コード例 #15
0
void Mass_spring_viewer::time_integration(float dt)
{
    switch (integration_)
    {
        case Euler:
        {
            /** \todo (Part 1) Implement Euler integration scheme
             \li The Particle class has variables position_t and velocity_t to store current values
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */
            compute_forces ();
            for (std::vector<Particle>::iterator p_it = body_.particles.begin (); p_it != body_.particles.end (); ++p_it)
              if (!p_it->locked)
              {
                /// 1)
                p_it->acceleration = p_it->force / p_it->mass;

                /// 2)
                p_it->position = p_it->position + dt * p_it->velocity;

                /// 3)
                p_it->velocity = p_it->velocity + dt * p_it->acceleration;
              }

            break;
        }

        case Midpoint:
        {
            /** \todo (Part 2) Implement the Midpoint time integration scheme
             \li The Particle class has variables position_t and velocity_t to store current values
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */
             compute_forces();
            for (std::vector<Particle>::iterator p_it = body_.particles.begin (); p_it != body_.particles.end (); ++p_it)
              if (!p_it->locked)
              {
                p_it->position_t = p_it->position;
                p_it->velocity_t = p_it->velocity;
                p_it->acceleration = p_it->force/p_it->mass;

                p_it->position += 0.5*dt * p_it->velocity;
                p_it->velocity += 0.5*dt * p_it->acceleration;
              }
            compute_forces();
            for (std::vector<Particle>::iterator p_it = body_.particles.begin (); p_it != body_.particles.end (); ++p_it)
              if (!p_it->locked)
              {
                p_it->acceleration = p_it->force / p_it->mass;


                p_it->position = p_it->position_t + dt * p_it->velocity;
                p_it->velocity = p_it->velocity_t + dt * p_it->acceleration;
              }

            break;
        }


        case Verlet:
        {
            /** \todo (Part 2) Implement the Verlet time integration scheme
             \li The Particle class has a variable acceleration to remember the previous values
             \li Hint: compute_forces() computes all forces for the current positions and velocities.
             */            
            compute_forces();
            // x(t)  v(t-h)
            for (std::vector<Particle>::iterator p_it = body_.particles.begin (); p_it != body_.particles.end (); ++p_it)
              if (!p_it->locked)
              {
                vec2 a = p_it->force / p_it->mass;
                p_it->velocity += 0.5*dt*(p_it->acceleration + a);

                // x(t) v(t)
                p_it->position += dt*p_it->velocity + 0.5*dt*dt*a;
                p_it->acceleration = a;
              }

            break;
        }

        case Implicit:
        {
            /// The usual force computation method is called, and then the jacobian matrix dF/dx is calculated
            compute_forces ();
            compute_jacobians ();

            /// Finally the linear system is composed and solved
            solver_.solve (dt, particle_mass_, body_.particles);

            break;
        }
    }


    // impulse-based collision handling
    if (collisions_ == Impulse_based)
    {
        impulse_based_collisions();
    }


    // E_c = 1/2 m*v^2
    float total_E = 0.0f;
    for (std::vector<Particle>::iterator p_it = body_.particles.begin (); p_it != body_.particles.end (); ++p_it)
        total_E += 0.5 * p_it->mass * dot(p_it->velocity, p_it->velocity);


    log_file << total_E << "\n";
    glutPostRedisplay();
}