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; }
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"); }
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(); }
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 ); }
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(); }
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
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
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(); }
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; } }
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, ¶m); 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, ¶m); #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; }
/* * 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; }
/* * 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; }
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; }
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(); } }
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(); }