/**Incorporates mass of each particle*/ double calc_mol_gyr_radius2(Molecule mol) { int i, id; double rg=0.0, M=0.0, com[3], diff_vec[3]; calc_mol_center_of_mass(mol, com); for(i=0; i<mol.part.n; i++) { id = mol.part.e[i]; vecsub(partCfg[id].r.p, com, diff_vec); rg += sqrlen(diff_vec); M += PMASS(partCfg[id]); } return (rg/M); }
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; }
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; }
void angularmomentum(int type, double *com) { int i, j; double tmp[3]; double pre_factor; com[0]=com[1]=com[2]=0.; updatePartCfg(WITHOUT_BONDS); for (j=0; j<n_part; j++) { if (type == partCfg[j].p.type) { vector_product(partCfg[j].r.p,partCfg[j].m.v,tmp); pre_factor=PMASS(partCfg[j]); for (i=0; i<3; i++) { com[i] += tmp[i]*pre_factor; } } } return; }
/* This is only done for the trapped molecules to save time */ void calc_local_mol_info (IntList *local_trapped_mols) { int mi, i,j, mol; Particle *p; int np, c; Cell *cell; int lm; int fixed; /* First reset all molecule masses,forces,centers of mass*/ for ( mi = 0 ; mi < n_molecules ; mi++ ) { topology[mi].mass = 0; for ( i = 0 ; i < 3 ; i++) { topology[mi].f[i] = 0.0; topology[mi].com[i] = 0.0; topology[mi].v[i] = 0.0; } } 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++) { mol = p[i].p.mol_id; if ( mol >= n_molecules ) { char *errtxt = runtime_error(128 + 3*TCL_INTEGER_SPACE); ERROR_SPRINTF(errtxt, "{ 094 can't calculate molforces no such molecule as %d }",mol); return; } /* Check to see if this molecule is fixed */ fixed =0; for(j = 0; j < 3; j++) { #ifdef EXTERNAL_FORCES if (topology[mol].trap_flag & COORD_FIXED(j)) fixed = 1; if (topology[mol].noforce_flag & COORD_FIXED(j)) fixed = 1; #endif } if (fixed) { topology[mol].mass += PMASS(p[i]); /* Unfold the particle */ unfold_position(p[i].r.p,p[i].l.i); for ( j = 0 ; j < 3 ; j++ ) { topology[mol].f[j] += p[i].f.f[j]; topology[mol].com[j] += p[i].r.p[j]*PMASS(p[i]); topology[mol].v[j] += p[i].m.v[j]*PMASS(p[i]); } /* Fold the particle back */ fold_position(p[i].r.p,p[i].l.i); } } } /* Final normalisation of centers of mass and velocity*/ for ( lm = 0 ; lm < local_trapped_mols->n; lm++ ) { mi = local_trapped_mols->e[lm]; for ( i = 0 ; i < 3 ; i++) { topology[mi].com[i] = topology[mi].com[i]/(double)(topology[mi].mass); topology[mi].v[i] = topology[mi].v[i]/(double)(topology[mi].mass); } } }
void analyze_rdfchain(double r_min, double r_max, int r_bins, double **_f1, double **_f2, double **_f3) { int i, j, ind, c_i, c_j, mon; double bin_width, inv_bin_width, factor, r_in, r_out, bin_volume, dist, chain_mass, *cm=NULL, *min_d=NULL, *f1=NULL, *f2=NULL, *f3=NULL; *_f1 = f1 = (double*)Utils::realloc(f1,r_bins*sizeof(double)); *_f2 = f2 = (double*)Utils::realloc(f2,r_bins*sizeof(double)); *_f3 = f3 = (double*)Utils::realloc(f3,r_bins*sizeof(double)); cm = (double*)Utils::realloc(cm,(chain_n_chains*3)*sizeof(double)); min_d = (double*)Utils::realloc(min_d,(chain_n_chains*chain_n_chains)*sizeof(double)); for(i=0; i<r_bins; i++) { f1[i] = f2[i] = f3[i] = 0.0; } bin_width = (r_max-r_min) / (double)r_bins; inv_bin_width = 1.0 / bin_width; for(c_i=0; c_i<chain_n_chains; c_i++) { cm[3*c_i] = cm[3*c_i+1] = cm[3*c_i+2] = 0.0; for(c_j=(c_i+1); c_j<chain_n_chains; c_j++) { min_d[c_i*chain_n_chains+c_j] = box_l[0] + box_l[1] + box_l[2]; } } for(c_i=0; c_i<chain_n_chains; c_i++) { for(i=0; i<chain_length; i++) { mon = chain_start + c_i*chain_length + i; cm[3*c_i]+= partCfg[mon].r.p[0]*PMASS(partCfg[mon]); cm[3*c_i+1]+= partCfg[mon].r.p[1]*PMASS(partCfg[mon]); cm[3*c_i+2]+= partCfg[mon].r.p[2]*PMASS(partCfg[mon]); for(c_j=(c_i+1); c_j<chain_n_chains; c_j++) { for(j=0; j<chain_length; j++) { dist = min_distance(partCfg[mon].r.p, partCfg[chain_start + c_j*chain_length+j].r.p); if ((dist > r_min) && (dist < r_max)) { ind = (int) ( (dist - r_min)*inv_bin_width ); f1[ind]+= 1.0; } if (dist<min_d[c_i*chain_n_chains+c_j]) min_d[c_i*chain_n_chains+c_j] = dist; } } } } chain_mass = 0; for(i=0; i<chain_length; i++) chain_mass+= PMASS(partCfg[i]); for(c_i=0; c_i<chain_n_chains; c_i++) { cm[3*c_i]/= chain_mass; cm[3*c_i+1]/= chain_mass; cm[3*c_i+2]/= chain_mass; for(c_j=(c_i+1); c_j<chain_n_chains; c_j++) { dist = min_d[c_i*chain_n_chains+c_j]; if ((dist > r_min) && (dist < r_max)) { ind = (int) ( (dist - r_min)*inv_bin_width ); f3[ind]+= 1.0; } } } for(c_i=0; c_i<chain_n_chains; c_i++) { for(c_j=(c_i+1); c_j<chain_n_chains; c_j++) { dist = min_distance(&cm[3*c_i],&cm[3*c_j]); if ((dist > r_min) && (dist < r_max)) { ind = (int) ( (dist - r_min)*inv_bin_width ); f2[ind]+= 1.0; } } } /* normalization */ factor = box_l[0]*box_l[1]*box_l[2] *1.5/PI/(chain_n_chains*(chain_n_chains-1)); for(i=0; i<r_bins; i++) { r_in = i*bin_width + r_min; r_out = r_in + bin_width; bin_volume = r_out*r_out*r_out - r_in*r_in*r_in; f1[i] *= factor / (bin_volume * chain_length*chain_length); f2[i] *= factor / bin_volume; f3[i] *= factor / bin_volume; } }
/** Calculate Random Force and Friction Force acting between particle p1 and p2 and add them to their forces. */ inline void add_dpd_thermo_pair_force(Particle *p1, Particle *p2, double d[3], double dist, double dist2) { extern double dpd_gamma,dpd_pref1, dpd_pref2,dpd_r_cut,dpd_r_cut_inv; extern int dpd_wf; #ifdef TRANS_DPD extern double dpd_tgamma, dpd_pref3, dpd_pref4,dpd_tr_cut,dpd_tr_cut_inv; extern int dpd_twf; #endif int j; // velocity difference between p1 and p2 double vel12_dot_d12=0.0; // inverse distance double dist_inv; // weighting functions for friction and random force double omega,omega2;// omega = w_R/dist double friction, noise; //Projection martix #ifdef TRANS_DPD int i; double P_times_dist_sqr[3][3]={{dist2,0,0},{0,dist2,0},{0,0,dist2}},noise_vec[3]; double f_D[3],f_R[3]; #endif double tmp; #ifdef DPD_MASS double massf; #endif #ifdef LEES_EDWARDS if( le_chatterjee_test_pair(p1, p2) == 0 ) return; #endif #ifdef EXTERNAL_FORCES // if any of the two particles is fixed in some direction then // do not add any dissipative or stochastic dpd force part // because dissipation-fluctuation theorem is violated if (dpd_ignore_fixed_particles) if ( (p1->l.ext_flag | p2->l.ext_flag) & COORDS_FIX_MASK) return; #endif #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(p1) || ifParticleIsVirtual(p2)) return; #endif #ifdef DPD_MASS_RED massf=2*PMASS(*p1)*PMASS(*p2)/(PMASS(*p1)+PMASS(*p2)); #endif #ifdef DPD_MASS_LIN massf=0.5*(PMASS(*p1)+PMASS(*p2)); #endif dist_inv = 1.0/dist; if((dist < dpd_r_cut)&&(dpd_gamma > 0.0)) { if ( dpd_wf == 1 ) //w_R=1 { omega = dist_inv; } else //w_R=(1-r/r_c) { omega = dist_inv- dpd_r_cut_inv; } #ifdef DPD_MASS omega*=sqrt(massf); #endif omega2 = SQR(omega); //DPD part // friction force prefactor for(j=0; j<3; j++) vel12_dot_d12 += (p1->m.v[j] - p2->m.v[j]) * d[j]; friction = dpd_pref1 * omega2 * vel12_dot_d12; // random force prefactor noise = dpd_pref2 * omega * (d_random()-0.5); for(j=0; j<3; j++) { p1->f.f[j] += ( tmp = (noise - friction)*d[j] ); p2->f.f[j] -= tmp; } } #ifdef TRANS_DPD //DPD2 part if ((dist < dpd_tr_cut)&&(dpd_tgamma > 0.0)){ if ( dpd_twf == 1 ) { omega = dist_inv; } else { omega = dist_inv- dpd_tr_cut_inv; } #ifdef DPD_MASS omega*=sqrt(massf); #endif omega2 = SQR(omega); for (i=0;i<3;i++){ //noise vector noise_vec[i]=d_random()-0.5; // Projection Matrix for (j=0;j<3;j++){ P_times_dist_sqr[i][j]-=d[i]*d[j]; } } for (i=0;i<3;i++){ //Damping force f_D[i]=0; //Random force f_R[i]=0; for (j=0;j<3;j++){ f_D[i]+=P_times_dist_sqr[i][j]*(p1->m.v[j] - p2->m.v[j]); f_R[i]+=P_times_dist_sqr[i][j]*noise_vec[j]; } //NOTE: velocity are scaled with time_step f_D[i]*=dpd_pref3*omega2; //NOTE: noise force scales with 1/sqrt(time_step f_R[i]*=dpd_pref4*omega*dist_inv; } for(j=0; j<3; j++) { tmp=f_R[j]-f_D[j]; p1->f.f[j] += tmp; p2->f.f[j] -= tmp; } } #endif }
inline void add_inter_dpd_pair_force(Particle *p1, Particle *p2, IA_parameters *ia_params, double d[3], double dist, double dist2) { int j; // velocity difference between p1 and p2 double vel12_dot_d12=0.0; // inverse distance double dist_inv; // weighting functions for friction and random force double omega,omega2;// omega = w_R/dist double friction, noise; //Projection martix int i; double P_times_dist_sqr[3][3]={{0,0,0},{0,0,0},{0,0,0}},noise_vec[3]; double f_D[3],f_R[3]; double tmp; #ifdef DPD_MASS double massf; #endif #ifdef EXTERNAL_FORCES // if any of the two particles is fixed in some direction then // do not add any dissipative or stochastic dpd force part // because dissipation-fluctuation theorem is violated if (dpd_ignore_fixed_particles) if ( (p1->l.ext_flag | p2->l.ext_flag) & COORDS_FIX_MASK) return; #endif #ifdef DPD_MASS_RED massf=2*PMASS(*p1)*PMASS(*p2)/(PMASS(*p1)+PMASS(*p2)); #endif #ifdef DPD_MASS_LIN massf=0.5*(PMASS(*p1)+PMASS(*p2)); #endif P_times_dist_sqr[0][0]=dist2; P_times_dist_sqr[1][1]=dist2; P_times_dist_sqr[2][2]=dist2; dist_inv = 1.0/dist; if((dist < ia_params->dpd_r_cut)&&(ia_params->dpd_gamma > 0.0)) { if ( dpd_wf == 1 ) { omega = dist_inv; } else { omega = dist_inv - 1.0/ia_params->dpd_r_cut; } #ifdef DPD_MASS omega*=sqrt(massf); #endif omega2 = SQR(omega); //DPD part // friction force prefactor for(j=0; j<3; j++) vel12_dot_d12 += (p1->m.v[j] - p2->m.v[j]) * d[j]; friction = ia_params->dpd_pref1 * omega2 * vel12_dot_d12; // random force prefactor noise = ia_params->dpd_pref2 * omega * (d_random()-0.5); for(j=0; j<3; j++) { p1->f.f[j] += ( tmp = (noise - friction)*d[j] ); p2->f.f[j] -= tmp; } } //DPD2 part if ((dist < ia_params->dpd_tr_cut)&&(ia_params->dpd_tgamma > 0.0)){ if ( ia_params->dpd_twf == 1 ) { omega = dist_inv; } else { omega = dist_inv- 1.0/ia_params->dpd_tr_cut; } #ifdef DPD_MASS omega*=sqrt(massf); #endif omega2 = SQR(omega); for (i=0;i<3;i++){ //noise vector noise_vec[i]=d_random()-0.5; // Projection Matrix for (j=0;j<3;j++){ P_times_dist_sqr[i][j]-=d[i]*d[j]; } } for (i=0;i<3;i++){ //Damping force f_D[i]=0; //Random force f_R[i]=0; for (j=0;j<3;j++){ f_D[i]+=P_times_dist_sqr[i][j]*(p1->m.v[j] - p2->m.v[j]); f_R[i]+=P_times_dist_sqr[i][j]*noise_vec[j]; } //NOTE: velocity are scaled with time_step f_D[i]*=ia_params->dpd_pref3*omega2; //NOTE: noise force scales with 1/sqrt(time_step f_R[i]*=ia_params->dpd_pref4*omega*dist_inv; } for(j=0; j<3; j++) { tmp=f_R[j]-f_D[j]; p1->f.f[j] += tmp; p2->f.f[j] -= tmp; } } }