void adress_update_weights(){ Particle *p; int i, np, c; Cell *cell; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { if (ifParticleIsVirtual(&p[i])) { p[i].p.adress_weight=adress_wf_vector((&p[i])->r.p); //printf("LOCAL %f %f\n", p[i].r.p[0], p[i].p.adress_weight); } } } for (c = 0; c < local_cells.n; c++) { cell = ghost_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { if (ifParticleIsVirtual(&p[i])) { p[i].p.adress_weight=adress_wf_vector((&p[i])->r.p); //printf("GHOST %f %f\n", p[i].r.p[0], p[i].p.adress_weight); } } } }
void put_mol_force_on_parts(Particle *p_com){ int i,j,mol_id; Particle *p; double force[3],M; #ifdef VIRTUAL_SITES_DEBUG int count=0; #endif mol_id=p_com->p.mol_id; for (i=0;i<3;i++){ force[i]=p_com->f.f[i]; p_com->f.f[i]=0.0; } #ifdef MASS M=0; for (i=0;i<topology[mol_id].part.n;i++){ p=local_particles[topology[mol_id].part.e[i]]; #ifdef VIRTUAL_SITES_DEBUG if (p==NULL){ ostringstream msg; msg <<"Particle does not exist in put_mol_force_on_parts! id= " << topology[mol_id].part.e[i] << "\n"; runtimeError(msg); return; } #endif if (ifParticleIsVirtual(p)) continue; M+=PMASS(*p); } #else M=topology[mol_id].part.n-1; #endif for (i=0;i<topology[mol_id].part.n;i++){ p=local_particles[topology[mol_id].part.e[i]]; #ifdef VIRTUAL_SITES_DEBUG if (p==NULL){ ostringstream msg; msg <<"Particle does not exist in put_mol_force_on_parts! id= " << topology[mol_id].part.e[i] << "\n"; runtimeError(msg); return; } #endif if (!ifParticleIsVirtual(p)) { for (j=0;j<3;j++){ p->f.f[j]+=PMASS(*p)*force[j]/M; } #ifdef VIRTUAL_SITES_DEBUG count++; #endif } } #ifdef VIRTUAL_SITES_DEBUG if (count!=topology[mol_id].part.n-1){ ostringstream msg; msg <<"There is more than one COM input_mol_force_on_parts! mol_id= " << mol_id << "\n"; runtimeError(msg); return; } #endif }
void put_mol_force_on_parts(Particle *p_com){ int i,j,mol_id; Particle *p; double force[3],M; #ifdef VIRTUAL_SITES_DEBUG int count=0; #endif mol_id=p_com->p.mol_id; for (i=0;i<3;i++){ force[i]=p_com->f.f[i]; p_com->f.f[i]=0.0; } #ifdef MASS M=0; for (i=0;i<topology[mol_id].part.n;i++){ p=local_particles[topology[mol_id].part.e[i]]; #ifdef VIRTUAL_SITES_DEBUG if (p==NULL){ char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"Particle does not exist in put_mol_force_on_parts! id=%i\n",topology[mol_id].part.e[i]); return; } #endif if (ifParticleIsVirtual(p)) continue; M+=PMASS(*p); } #else M=topology[mol_id].part.n-1; #endif for (i=0;i<topology[mol_id].part.n;i++){ p=local_particles[topology[mol_id].part.e[i]]; #ifdef VIRTUAL_SITES_DEBUG if (p==NULL){ char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"Particle does not exist in put_mol_force_on_parts! id=%i\n",topology[mol_id].part.e[i]); return; } #endif if (!ifParticleIsVirtual(p)) { for (j=0;j<3;j++){ p->f.f[j]+=PMASS(*p)*force[j]/M; } #ifdef VIRTUAL_SITES_DEBUG count++; #endif } } #ifdef VIRTUAL_SITES_DEBUG if (count!=topology[mol_id].part.n-1){ char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"There is more than one COM input_mol_force_on_parts! mol_id=%i\n",mol_id); return; } #endif }
/** Calculate kinetic energies for one particle. @param p1 particle for which to calculate energies */ inline void add_kinetic_energy(Particle *p1) { #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(p1)) return; #endif /* kinetic energy */ energy.data.e[0] += (SQR(p1->m.v[0]) + SQR(p1->m.v[1]) + SQR(p1->m.v[2]))*PMASS(*p1); #ifdef ROTATION #ifdef ROTATION_PER_PARTICLE if (p1->p.rotation) #endif { #ifdef ROTATIONAL_INERTIA /* the rotational part is added to the total kinetic energy; Here we use the rotational inertia */ energy.data.e[0] += (SQR(p1->m.omega[0])*p1->p.rinertia[0] + SQR(p1->m.omega[1])*p1->p.rinertia[1] + SQR(p1->m.omega[2])*p1->p.rinertia[2])*time_step*time_step; #else /* the rotational part is added to the total kinetic energy; at the moment, we assume unit inertia tensor I=(1,1,1) */ energy.data.e[0] += (SQR(p1->m.omega[0]) + SQR(p1->m.omega[1]) + SQR(p1->m.omega[2]))*time_step*time_step; #endif } #endif }
// Calculates center of mass of a particle int calc_mol_pos_cfg(Particle *p_com,double r_com[3]){ int i,j,mol_id; double M=0; Particle *p; #ifdef VIRTUAL_SITES_DEBUG int count=0; #endif for (i=0;i<3;i++){ r_com[i]=0.0; } mol_id=p_com->p.mol_id; for (i=0;i<topology[mol_id].part.n;i++){ p=&partCfg[topology[mol_id].part.e[i]]; if (ifParticleIsVirtual(p)) continue; for (j=0;j<3;j++){ r_com[j] += PMASS(*p)*p->r.p[j]; } M+=PMASS(*p); #ifdef VIRTUAL_SITES_DEBUG count++; #endif } for (j=0;j<3;j++){ r_com[j] /= M; } #ifdef VIRTUAL_SITES_DEBUG if (count!=topology[mol_id].part.n-1){ fprintf(stderr,"There is more than one COM in calc_mol_pos_cfg! mol_id=%i\n",mol_id); return 0; } #endif return 1; }
/** initialize the forces for a ghost particle */ MDINLINE void init_ghost_force(Particle *part) { #ifdef ADRESS if (ifParticleIsVirtual(part)) { part->p.adress_weight=adress_wf_vector(part->r.p); } #endif part->f.f[0] = 0; part->f.f[1] = 0; part->f.f[2] = 0; #ifdef ROTATION { double scale; /* set torque to zero */ part->f.torque[0] = 0; part->f.torque[1] = 0; part->f.torque[2] = 0; /* and rescale quaternion, so it is exactly of unit length */ scale = sqrt( SQR(part->r.quat[0]) + SQR(part->r.quat[1]) + SQR(part->r.quat[2]) + SQR(part->r.quat[3])); part->r.quat[0]/= scale; part->r.quat[1]/= scale; part->r.quat[2]/= scale; part->r.quat[3]/= scale; } #endif }
/* momentum update step of ghmc */ void simple_momentum_update() { int i, j, c, np; Particle *part; double sigmat, sigmar; sigmat = sqrt(temperature); sigmar = sqrt(temperature); for (c = 0; c < local_cells.n; c++) { np = local_cells.cell[c]->n; part = local_cells.cell[c]->part; for (i = 0; i < np; i++) { #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(&part[i])) continue; #endif #ifdef MASS sigmat = sqrt(temperature / PMASS(part[i])); #endif for (j = 0; j < 3; j++) { part[i].m.v[j] = sigmat*gaussian_random()*time_step; #ifdef ROTATION #ifdef ROTATIONAL_INERTIA sigmar = sqrt(temperature / part[i].p.rinertia[j]); #endif part[i].m.omega[j] = sigmar*gaussian_random(); #endif } } } //fprintf(stderr,"%d: temp after simple update: %f\n",this_node,calc_local_temp()); }
Particle *get_mol_com_particle(Particle *calling_p){ int mol_id; int i; Particle *p; mol_id=calling_p->p.mol_id; if (mol_id < 0) { char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"Particle does not have a mol id! pnr=%i\n", calling_p->p.identity); return NULL; } for (i=0;i<topology[mol_id].part.n;i++){ p=local_particles[topology[mol_id].part.e[i]]; if (p==NULL){ char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"Particle does not exist in put_mol_force_on_parts! id=%i\n",topology[mol_id].part.e[i]); return NULL; } if (ifParticleIsVirtual(p)) { return p; } } char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"No com found in get_mol_com_particleParticle does not exist in put_mol_force_on_parts! pnr=%i\n",calling_p->p.identity); return NULL; return calling_p; }
Particle *get_mol_com_particle(Particle *calling_p) { int mol_id; int i; Particle *p; mol_id=calling_p->p.mol_id; for (i=0; i<topology[mol_id].part.n; i++) { p=local_particles[topology[mol_id].part.e[i]]; #ifdef VIRTUAL_SITES_DEBUG if (p==NULL) { char *errtxt = runtime_error(128 + 3*TCL_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"Particle does not exist in put_mol_force_on_parts! id=%i\n",topology[mol_id].part.e[i]); return NULL; } #endif if (ifParticleIsVirtual(p)) { return p; } } #ifdef VIRTUAL_SITES_DEBUG char *errtxt = runtime_error(128 + 3*TCL_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"No com found in get_mol_com_particleParticle does not exist in put_mol_force_on_parts! pnr=%i\n",calling_p->p.identity); return NULL; #endif return calling_p; }
Particle *get_mol_com_particle(Particle *calling_p){ int mol_id; int i; Particle *p; mol_id=calling_p->p.mol_id; if (mol_id < 0) { ostringstream msg; msg <<"Particle does not have a mol id! pnr= " << calling_p->p.identity << "\n"; runtimeError(msg); return NULL; } for (i=0;i<topology[mol_id].part.n;i++){ p=local_particles[topology[mol_id].part.e[i]]; if (p==NULL){ ostringstream msg; msg <<"Particle does not exist in put_mol_force_on_parts! id= " << topology[mol_id].part.e[i] << "\n"; runtimeError(msg); return NULL; } if (ifParticleIsVirtual(p)) { return p; } } ostringstream msg; msg <<"No com found in get_mol_com_particleParticle does not exist in put_mol_force_on_parts! pnr= " << calling_p->p.identity << "\n"; runtimeError(msg); return NULL; return calling_p; }
/* momentum update step of ghmc with temperature scaling */ void tscale_momentum_update() { int i, j, c, np; Particle *part; //fprintf(stderr,"%d: temp before update: %f\n",this_node,calc_local_temp()); save_last_state(); simple_momentum_update(); //fprintf(stderr,"%d: temp after simple update: %f\n",this_node,calc_local_temp()); double tempt, tempr; calc_kinetic(&tempt, &tempr); tempt /= (1.5*n_total_particles); tempr /= (1.5*n_total_particles); double scalet = sqrt(temperature / tempt); #ifdef ROTATION double scaler = sqrt(temperature / tempr); #endif for (c = 0; c < local_cells.n; c++) { np = local_cells.cell[c]->n; part = local_cells.cell[c]->part; for (i = 0; i < np; i++) { for (j = 0; j < 3; j++) { part[i].m.v[j] *= scalet; #ifdef ROTATION part[i].m.omega[j] *= scaler; #endif } } } //fprintf(stderr,"%d: temp after scale: %f\n",this_node,calc_local_temp()); for (c = 0; c < local_cells.n; c++) { np = local_cells.cell[c]->n; part = local_cells.cell[c]->part; for (i = 0; i < np; i++) { #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(&part[i])) continue; #endif for (j = 0; j < 3; j++) { part[i].m.v[j] = cosp*(part[i].l.m_ls.v[j])+sinp*(part[i].m.v[j]); #ifdef ROTATION part[i].m.omega[j] = cosp*(part[i].l.m_ls.omega[j])+sinp*(part[i].m.omega[j]); #endif } } } //fprintf(stderr,"%d : temp after partial update: %f\n",this_node,calc_local_temp()); }
bool steepest_descent_step(void) { Cell *cell; Particle *p; int c, i, j, np; double f_max = -std::numeric_limits<double>::max(); double f; /* Verlet list criterion */ const double skin2 = SQR(0.5*skin); double f_max_global; double dx[3], dx2; const double max_dx2 = SQR(params->max_displacement); for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { f = 0.0; dx2 = 0.0; #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(&p[i])) continue; #endif for(j=0; j < 3; j++){ #ifdef EXTERNAL_FORCES if (!(p[i].p.ext_flag & COORD_FIXED(j))) #endif { f += SQR(p[i].f.f[j]); dx[j] = params->gamma * p[i].f.f[j]; dx2 += SQR(dx[j]); MINIMIZE_ENERGY_TRACE(printf("part %d dim %d dx %e gamma*f %e\n", i, j, dx[j], params->gamma * p[i].f.f[j])); } #ifdef EXTERNAL_FORCES else { dx[j] = 0.0; } #endif } if(dx2 <= max_dx2) { p[i].r.p[0] += dx[0]; p[i].r.p[1] += dx[1]; p[i].r.p[2] += dx[2]; } else { const double c = params->max_displacement/std::sqrt(dx2); p[i].r.p[0] += c*dx[0]; p[i].r.p[1] += c*dx[1]; p[i].r.p[2] += c*dx[2]; } if(distance2(p[i].r.p,p[i].l.p_old) > skin2 ) resort_particles = 1; f_max = std::max(f_max, f); } } MINIMIZE_ENERGY_TRACE(printf("f_max %e resort_particles %d\n", f_max, resort_particles)); announce_resort_particles(); MPI_Allreduce(&f_max, &f_max_global, 1, MPI_DOUBLE, MPI_MAX, comm_cart); return (sqrt(f_max_global) < params->f_max); }
void rescale_forces_propagate_vel() { Cell *cell; Particle *p; int i, j, np, c; double scale; #ifdef NPT if(integ_switch == INTEG_METHOD_NPT_ISO){ nptiso.p_vel[0] = nptiso.p_vel[1] = nptiso.p_vel[2] = 0.0;} #endif scale = 0.5 * time_step * time_step; INTEG_TRACE(fprintf(stderr,"%d: rescale_forces_propagate_vel:\n",this_node)); for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { check_particle_force(&p[i]); /* Rescale forces: f_rescaled = 0.5*dt*dt * f_calculated * (1/mass) */ p[i].f.f[0] *= scale/PMASS(p[i]); p[i].f.f[1] *= scale/PMASS(p[i]); p[i].f.f[2] *= scale/PMASS(p[i]); ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT: SCAL f = (%.3e,%.3e,%.3e) v_old = (%.3e,%.3e,%.3e)\n",this_node,p[i].f.f[0],p[i].f.f[1],p[i].f.f[2],p[i].m.v[0],p[i].m.v[1],p[i].m.v[2])); #ifdef VIRTUAL_SITES // Virtual sites are not propagated during integration if (ifParticleIsVirtual(&p[i])) continue; #endif for(j = 0; j < 3 ; j++) { #ifdef EXTERNAL_FORCES if (!(p[i].l.ext_flag & COORD_FIXED(j))) { #endif #ifdef NPT if(integ_switch == INTEG_METHOD_NPT_ISO && ( nptiso.geometry & nptiso.nptgeom_dir[j] )) { nptiso.p_vel[j] += SQR(p[i].m.v[j])*PMASS(p[i]); p[i].m.v[j] += p[i].f.f[j] + friction_therm0_nptiso(p[i].m.v[j])/PMASS(p[i]); } else #endif /* Propagate velocity: v(t+dt) = v(t+0.5*dt) + 0.5*dt * f(t+dt) */ { p[i].m.v[j] += p[i].f.f[j]; } #ifdef EXTERNAL_FORCES } #endif } ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT: PV_2 v_new = (%.3e,%.3e,%.3e)\n",this_node,p[i].m.v[0],p[i].m.v[1],p[i].m.v[2])); } } #ifdef NPT finalize_p_inst_npt(); #endif }
void update_mol_vel_particle(Particle *p){ int j; double v_com[3]; if (ifParticleIsVirtual(p)) { calc_mol_vel(p,v_com); for (j=0;j<3;j++){ p->m.v[j] = v_com[j]; } } }
void update_mol_pos_particle(Particle *p){ int j; double r_com[3]; if (ifParticleIsVirtual(p)) { calc_mol_pos(p,r_com); for (j=0;j<3;j++){ p->r.p[j] = r_com[j]; } } }
/** propagate angular velocities and quaternions \todo implement for fixed_coord_flag */ void propagate_omega_quat() { Particle *p; Cell *cell; int c,i,j, np; double lambda, dt2, dt4, dtdt, dtdt2; dt2 = time_step*0.5; dt4 = time_step*0.25; dtdt = time_step*time_step; dtdt2 = dtdt*0.5; INTEG_TRACE(fprintf(stderr,"%d: propagate_omega_quat:\n",this_node)); for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { double Qd[4], Qdd[4], S[3], Wd[3]; #ifdef VIRTUAL_SITES // Virtual sites are not propagated in the integration step if (ifParticleIsVirtual(&p[i])) continue; #endif define_Qdd(&p[i], Qd, Qdd, S, Wd); lambda = 1 - S[0]*dtdt2 - sqrt(1 - dtdt*(S[0] + time_step*(S[1] + dt4*(S[2]-S[0]*S[0])))); for(j=0; j < 3; j++){ p[i].m.omega[j]+= dt2*Wd[j]; } ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT: PV_1 v_new = (%.3e,%.3e,%.3e)\n",this_node,p[i].m.v[0],p[i].m.v[1],p[i].m.v[2])); p[i].r.quat[0]+= time_step*(Qd[0] + dt2*Qdd[0]) - lambda*p[i].r.quat[0]; p[i].r.quat[1]+= time_step*(Qd[1] + dt2*Qdd[1]) - lambda*p[i].r.quat[1]; p[i].r.quat[2]+= time_step*(Qd[2] + dt2*Qdd[2]) - lambda*p[i].r.quat[2]; p[i].r.quat[3]+= time_step*(Qd[3] + dt2*Qdd[3]) - lambda*p[i].r.quat[3]; // Update the director convert_quat_to_quatu(p[i].r.quat, p[i].r.quatu); #ifdef DIPOLES // When dipoles are enabled, update dipole moment convert_quatu_to_dip(p[i].r.quatu, p[i].p.dipm, p[i].r.dip); #endif ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT: PPOS p = (%.3f,%.3f,%.3f)\n",this_node,p[i].r.p[0],p[i].r.p[1],p[i].r.p[2])); } } }
Particle *get_mol_com_particle_from_molid_cfg(int mol_id){ int i; Particle *p; for (i=0;i<topology[mol_id].part.n;i++){ p=&partCfg[topology[mol_id].part.e[i]]; if (ifParticleIsVirtual(p)){ return p; } } #ifdef VIRTUAL_SITES_DEBUG fprintf(stderr,"No com found in get_mol_com_particle_from_molid_cfg ! mol_id=%i\n",mol_id); #endif return NULL; }
void update_mol_pos() { Particle *p; int i, np, c; Cell *cell; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { if (ifParticleIsVirtual(&p[i])) update_mol_pos_particle(&p[i]); } //only for real particles } }
// Distribute forces that have accumulated on virtual particles to the // associated real particles void distribute_mol_force() { // Iterate over all the particles in the local cells Particle *p; int i, np, c; Cell *cell; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { // We only care about virtual particles if (ifParticleIsVirtual(&p[i])) { update_mol_pos_particle(&p[i]); // First obtain the real particle responsible for this virtual particle: Particle *p_real = vs_relative_get_real_particle(&p[i]); // Get distance vector pointing from real to virtual particle, respecting periodic boundary i // conditions double d[3]; get_mi_vector(d,p[i].r.p,p_real->r.p); // The rules for transfering forces are: // F_realParticle +=F_virtualParticle // T_realParticle +=f_realParticle \times (r_virtualParticle-r_realParticle) // Calculate torque to be added on real particle double tmp[3]; vector_product(d,p[i].f.f,tmp); // Add forces and torques int j; // printf("Particle %d gets torque from %f %f %f of particle %d\n",p_real->p.identity, p[i].f.f[0], p[i].f.f[1],p[i].f.f[2], p[i].p.identity); for (j=0;j<3;j++) { p_real->f.torque[j]+=tmp[j]; // printf("%f ",tmp[j]); p_real->f.f[j]+=p[i].f.f[j]; // Clear forces on virtual particle p[i].f.f[j]=0; } } } } }
void update_mol_vel() { #ifndef VIRTUAL_SITES_NO_VELOCITY Particle *p; int i, np, c; Cell *cell; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { if (ifParticleIsVirtual(&p[i])) update_mol_vel_particle(&p[i]); } } #endif }
/* but p_com is a real particle */ void calc_mol_pos(Particle *p_com,double r_com[3]){ int i,j,mol_id; double M=0; double vec12[3]; Particle *p; #ifdef VIRTUAL_SITES_DEBUG int count=0; #endif for (i=0;i<3;i++){ r_com[i]=0.0; } mol_id=p_com->p.mol_id; for (i=0;i<topology[mol_id].part.n;i++){ p=local_particles[topology[mol_id].part.e[i]]; #ifdef VIRTUAL_SITES_DEBUG if (p==NULL){ ostringstream msg; msg <<"Particle does not exist in calc_mol_pos! id= " << topology[mol_id].part.e[i] << "\n"; runtimeError(msg); return; } #endif if (ifParticleIsVirtual(p)) continue; get_mi_vector(vec12,p->r.p, p_com->r.p); for (j=0;j<3;j++){ r_com[j] += PMASS(*p)*vec12[j]; } M+=PMASS(*p); #ifdef VIRTUAL_SITES_DEBUG count++; #endif } for (j=0;j<3;j++){ r_com[j] /= M; r_com[j] += p_com->r.p[j]; } #ifdef VIRTUAL_SITES_DEBUG if (count!=topology[mol_id].part.n-1){ ostringstream msg; msg <<"There is more than one COM in calc_mol_pos! mol_id= " << mol_id << "\n"; runtimeError(msg); return; } #endif }
void distribute_mol_force() { Particle *p; int i, np, c; Cell *cell; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { if (ifParticleIsVirtual(&p[i])) { if (sqrlen(p[i].f.f)!=0){ put_mol_force_on_parts(&p[i]); } } } } }
// Rigid body conribution to scalar pressure and stress tensor void vs_relative_pressure_and_stress_tensor(double* pressure, double* stress_tensor) { // Division by 3 volume is somewhere else. (pressure.cpp after all presure calculations) // Iterate over all the particles in the local cells Particle *p; int i, np, c; Cell *cell; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { // We only care about virtual particles if (!ifParticleIsVirtual(&p[i])) continue; update_mol_pos_particle(&p[i]); // First obtain the real particle responsible for this virtual particle: Particle *p_real = vs_relative_get_real_particle(&p[i]); // Get distance vector pointing from real to virtual particle, respecting periodic boundary i // conditions double d[3]; get_mi_vector(d,p_real->r.p,p[i].r.p); // Stress tensor conribution for (int k =0; k<3;k++) for (int l =0;l<3;l++) stress_tensor[k*3+l] +=p[i].f.f[k] *d[l]; // Pressure = 1/3 trace of stress tensor // but the 1/3 is applied somewhere else. *pressure +=(p[i].f.f[0] *d[0] +p[i].f.f[1] *d[1] +p[i].f.f[2] *d[2]); } } *pressure/=0.5*time_step*time_step; for (i=0;i<9;i++) stress_tensor[i]/=0.5*time_step*time_step; }
void calc_kinetic(double *ek_trans , double *ek_rot) { int i, c, np; Particle *part; double et = 0.0, er = 0.0; for (c = 0; c < local_cells.n; c++) { np = local_cells.cell[c]->n; part = local_cells.cell[c]->part; for (i = 0; i < np; i++) { #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(&part[i])) continue; #endif /* kinetic energy */ et += (SQR(part[i].m.v[0]) + SQR(part[i].m.v[1]) + SQR(part[i].m.v[2]))*PMASS(part[i]); /* rotational energy */ #ifdef ROTATION #ifdef ROTATIONAL_INERTIA er += SQR(part[i].m.omega[0])*part[i].p.rinertia[0] + SQR(part[i].m.omega[1])*part[i].p.rinertia[1] + SQR(part[i].m.omega[2])*part[i].p.rinertia[2]; #else er += SQR(part[i].m.omega[0]) + SQR(part[i].m.omega[1]) + SQR(part[i].m.omega[2]); #endif #endif } } MPI_Allreduce(MPI_IN_PLACE, &et, 1, MPI_DOUBLE, MPI_SUM, comm_cart); MPI_Allreduce(MPI_IN_PLACE, &er, 1, MPI_DOUBLE, MPI_SUM, comm_cart); et /= (2.0*time_step*time_step); #ifdef ROTATION er /= 2.0; #endif *ek_trans=et; *ek_rot=er; }
/* but p_com is a real particle */ void calc_mol_pos(Particle *p_com,double r_com[3]){ int i,j,mol_id; double M=0; double vec12[3]; Particle *p; #ifdef VIRTUAL_SITES_DEBUG int count=0; #endif for (i=0;i<3;i++){ r_com[i]=0.0; } mol_id=p_com->p.mol_id; for (i=0;i<topology[mol_id].part.n;i++){ p=local_particles[topology[mol_id].part.e[i]]; #ifdef VIRTUAL_SITES_DEBUG if (p==NULL){ char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"Particle does not exist in calc_mol_pos! id=%i\n",topology[mol_id].part.e[i]); return; } #endif if (ifParticleIsVirtual(p)) continue; get_mi_vector(vec12,p->r.p, p_com->r.p); for (j=0;j<3;j++){ r_com[j] += PMASS(*p)*vec12[j]; } M+=PMASS(*p); #ifdef VIRTUAL_SITES_DEBUG count++; #endif } for (j=0;j<3;j++){ r_com[j] /= M; r_com[j] += p_com->r.p[j]; } #ifdef VIRTUAL_SITES_DEBUG if (count!=topology[mol_id].part.n-1){ char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); ERROR_SPRINTF(errtxt,"There is more than one COM in calc_mol_pos! mol_id=%i\n",mol_id); return; } #endif }
void calc_dipole_of_molecule(int mol_id,double dipole[4]){ int j,k; Particle *p,*p_first=NULL; double vec12[3]; dipole[0]=dipole[1]=dipole[2]=dipole[3]=0.0; for (j=0;j<topology[mol_id].part.n;j++){ p=&partCfg[topology[mol_id].part.e[j]]; if (ifParticleIsVirtual(p)) continue; if (p_first==NULL){ p_first=p; } else { get_mi_vector(vec12,p->r.p, p_first->r.p); for (k=0;k<3;k++){ dipole[k] += p->p.q*vec12[k]; } } dipole[3]+=p->p.q; } }
double calc_energy_kinetic_mol(int type){ double E_kin=0; int i; Particle *p_com; for (i=0;i<n_molecules;i++){ if (topology[i].type == type){ p_com=get_mol_com_particle_from_molid_cfg(i); #ifdef VIRTUAL_SITES_DEBUG if (p_com==NULL){ return -(i); } if (!ifParticleIsVirtual(p_com)){ return -(i); } #endif E_kin+=PMASS(*p_com)*sqrlen(p_com->m.v); } } E_kin*=0.5/time_step/time_step; return E_kin; }
int tclcommand_analyze_parse_and_print_check_mol(Tcl_Interp *interp,int argc, char **argv){ int j,count=0; double dist; char buffer[TCL_DOUBLE_SPACE]; Particle p; updatePartCfg(WITHOUT_BONDS); for(j=0; j<n_total_particles; j++){ if (!ifParticleIsVirtual(&partCfg[j])) continue; get_particle_data(j,&p); //dist=min_distance(partCfg[j].r.p,p.r.p); unfold_position(p.r.p,p.l.i); dist=distance(partCfg[j].r.p,p.r.p); if (dist > 0.01){ if (count==0) Tcl_AppendResult(interp,"BEGIN Particle Missmatch: \n", (char *)NULL); sprintf(buffer,"%i",j); Tcl_AppendResult(interp,"Particle ",buffer, (char *)NULL); Tcl_PrintDouble(interp,partCfg[j].r.p[0] , buffer); Tcl_AppendResult(interp," partCfg x ",buffer, (char *)NULL); Tcl_PrintDouble(interp,partCfg[j].r.p[1] , buffer); Tcl_AppendResult(interp," y ",buffer, (char *)NULL); Tcl_PrintDouble(interp,partCfg[j].r.p[2] , buffer); Tcl_AppendResult(interp," z ",buffer, (char *)NULL); Tcl_PrintDouble(interp,p.r.p[0] , buffer); Tcl_AppendResult(interp," my_partCfg x ",buffer, (char *)NULL); Tcl_PrintDouble(interp,p.r.p[1] , buffer); Tcl_AppendResult(interp," y ",buffer, (char *)NULL); Tcl_PrintDouble(interp,p.r.p[2] , buffer); Tcl_AppendResult(interp," z ",buffer, (char *)NULL); Tcl_PrintDouble(interp, dist, buffer); Tcl_AppendResult(interp," dist ",buffer,"\n", (char *)NULL); count++; } } if (count!=0){ Tcl_AppendResult(interp,"END Particle Missmatch\n", (char *)NULL); return(TCL_ERROR); } return(TCL_OK); }
void propagate_press_box_pos_and_rescale_npt() { #ifdef NPT if(integ_switch == INTEG_METHOD_NPT_ISO) { Cell *cell; Particle *p; int i, j, np, c; double scal[3]={0.,0.,0.}, L_new=0.0; /* finalize derivation of p_inst */ finalize_p_inst_npt(); /* adjust \ref nptiso_struct::nptiso.volume; prepare pos- and vel-rescaling */ if (this_node == 0) { nptiso.volume += nptiso.inv_piston*nptiso.p_diff*0.5*time_step; scal[2] = SQR(box_l[nptiso.non_const_dim])/pow(nptiso.volume,2.0/nptiso.dimension); nptiso.volume += nptiso.inv_piston*nptiso.p_diff*0.5*time_step; if (nptiso.volume < 0.0) { char *errtxt = runtime_error(128 + 3*TCL_DOUBLE_SPACE); ERROR_SPRINTF(errtxt, "{015 your choice of piston=%g, dt=%g, p_diff=%g just caused the volume to become negative, decrease dt} ", nptiso.piston,time_step,nptiso.p_diff); nptiso.volume = box_l[0]*box_l[1]*box_l[2]; scal[2] = 1; } L_new = pow(nptiso.volume,1.0/nptiso.dimension); // printf(stdout,"Lnew, %f: volume, %f: dim, %f: press, %f \n", L_new, nptiso.volume, nptiso.dimension,nptiso.p_inst ); // fflush(stdout); scal[1] = L_new/box_l[nptiso.non_const_dim]; scal[0] = 1/scal[1]; } MPI_Bcast(scal, 3, MPI_DOUBLE, 0, MPI_COMM_WORLD); /* propagate positions while rescaling positions and velocities */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(&p[i])) continue; #endif for(j=0; j < 3; j++){ #ifdef EXTERNAL_FORCES if (!(p[i].l.ext_flag & COORD_FIXED(j))) { #endif if(nptiso.geometry & nptiso.nptgeom_dir[j]) { p[i].r.p[j] = scal[1]*(p[i].r.p[j] + scal[2]*p[i].m.v[j]); p[i].l.p_old[j] *= scal[1]; p[i].m.v[j] *= scal[0]; } else { p[i].r.p[j] += p[i].m.v[j]; } #ifdef EXTERNAL_FORCES } #endif } ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT:PV_1 v_new=(%.3e,%.3e,%.3e)\n",this_node,p[i].m.v[0],p[i].m.v[1],p[i].m.v[2])); ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT:PPOS p=(%.3f,%.3f,%.3f)\n",this_node,p[i].r.p[0],p[i].r.p[1],p[i].r.p[2])); #ifdef ADDITIONAL_CHECKS force_and_velocity_check(&p[i]); #endif } } resort_particles = 1; /* Apply new volume to the box-length, communicate it, and account for necessary adjustments to the cell geometry */ if (this_node == 0) { for ( i = 0 ; i < 3 ; i++ ){ if ( nptiso.geometry & nptiso.nptgeom_dir[i] ) { box_l[i] = L_new; } else if ( nptiso.cubic_box ) { box_l[i] = L_new; } } } MPI_Bcast(box_l, 3, MPI_DOUBLE, 0, MPI_COMM_WORLD); on_NpT_boxl_change(); }
/** initialize the forces for a real particle */ MDINLINE void init_local_particle_force(Particle *part) { #ifdef ADRESS double new_weight; if (ifParticleIsVirtual(part)) { new_weight = adress_wf_vector(part->r.p); #ifdef ADRESS_INIT double old_weight = part->p.adress_weight; if(new_weight>0 && old_weight==0){ double rand_cm_pos[3], rand_cm_vel[3], rand_weight, new_pos, old_pos; int it, dim, this_mol_id=part->p.mol_id, rand_mol_id, rand_type; int n_ats_this_mol=topology[this_mol_id].part.n, n_ats_rand_mol; //look for a random explicit particle rand_type=-1; rand_weight=-1; rand_mol_id=-1; n_ats_rand_mol=-1; while(rand_type != part->p.type || rand_weight != 1 || n_ats_rand_mol != n_ats_this_mol){ rand_mol_id = i_random(n_molecules); rand_type = local_particles[(topology[rand_mol_id].part.e[0])]->p.type; rand_weight = local_particles[(topology[rand_mol_id].part.e[0])]->p.adress_weight; n_ats_rand_mol = topology[rand_mol_id].part.n; if(!ifParticleIsVirtual(local_particles[(topology[rand_mol_id].part.e[0])])) fprintf(stderr,"No virtual site found on molecule %d, with %d total molecules.\n",rand_mol_id, n_molecules); } //store CM position and velocity for(dim=0;dim<3;dim++){ rand_cm_pos[dim]=local_particles[(topology[rand_mol_id].part.e[0])]->r.p[dim]; rand_cm_vel[dim]=local_particles[(topology[rand_mol_id].part.e[0])]->m.v[dim]; } //assign new positions and velocities to the atoms for(it=0;it<n_ats_this_mol;it++){ if (!ifParticleIsVirtual(local_particles[topology[rand_mol_id].part.e[it]])) { for(dim=0;dim<3;dim++){ old_pos = local_particles[topology[this_mol_id].part.e[it]]->r.p[dim]; new_pos = local_particles[topology[rand_mol_id].part.e[it]]->r.p[dim]-rand_cm_pos[dim]+part->r.p[dim]; //MAKE SURE THEY ARE IN THE SAME BOX while(new_pos-old_pos>box_l[dim]*0.5) new_pos=new_pos-box_l[dim]; while(new_pos-old_pos<-box_l[dim]*0.5) new_pos=new_pos+box_l[dim]; local_particles[(topology[this_mol_id].part.e[it])]->r.p[dim] = new_pos; local_particles[(topology[this_mol_id].part.e[it])]->m.v[dim] = local_particles[(topology[rand_mol_id].part.e[it])]->m.v[dim]-rand_cm_vel[dim]+part->m.v[dim]; } } } } #endif part->p.adress_weight=new_weight; } #endif if ( thermo_switch & THERMO_LANGEVIN ) friction_thermo_langevin(part); else { part->f.f[0] = 0; part->f.f[1] = 0; part->f.f[2] = 0; } #ifdef EXTERNAL_FORCES if(part->l.ext_flag & PARTICLE_EXT_FORCE) { part->f.f[0] += part->l.ext_force[0]; part->f.f[1] += part->l.ext_force[1]; part->f.f[2] += part->l.ext_force[2]; } #endif #ifdef ROTATION { double scale; /* set torque to zero */ part->f.torque[0] = 0; part->f.torque[1] = 0; part->f.torque[2] = 0; /* and rescale quaternion, so it is exactly of unit length */ scale = sqrt( SQR(part->r.quat[0]) + SQR(part->r.quat[1]) + SQR(part->r.quat[2]) + SQR(part->r.quat[3])); part->r.quat[0]/= scale; part->r.quat[1]/= scale; part->r.quat[2]/= scale; part->r.quat[3]/= scale; } #endif #ifdef ADRESS /* #ifdef THERMODYNAMIC_FORCE */ if(ifParticleIsVirtual(part)) if(part->p.adress_weight > 0 && part->p.adress_weight < 1) add_thermodynamic_force(part); /* #endif */ #endif }