/* monte carlo step of ghmc - evaluation stage */ void ghmc_mc() { INTEG_TRACE(fprintf(stderr,"%d: ghmc_mc:\n",this_node)); double boltzmann; int ekin_update_flag = 0; hamiltonian_calc(ekin_update_flag); //make MC decision only on the master if (this_node==0) { ghmcdata.att++; //metropolis algorithm boltzmann = ghmcdata.hmlt_new - ghmcdata.hmlt_old; if (boltzmann < 0) boltzmann = 1.0; else if (boltzmann > 30) boltzmann = 0.0; else boltzmann = exp(-beta*boltzmann); //fprintf(stderr,"old hamiltonian : %f, new hamiltonian: % f, boltzmann factor: %f\n",ghmcdata.hmlt_old,ghmcdata.hmlt_new,boltzmann); if ( d_random() < boltzmann) { ghmcdata.acc++; ghmc_mc_res = GHMC_MOVE_ACCEPT; } else { ghmc_mc_res = GHMC_MOVE_REJECT; } } //let all nodes know about the MC decision result mpi_bcast_parameter(FIELD_GHMC_RES); if (ghmc_mc_res == GHMC_MOVE_ACCEPT) { save_last_state(); //fprintf(stderr,"%d: mc move accepted\n",this_node); } else { load_last_state(); //fprintf(stderr,"%d: mc move rejected\n",this_node); //if the move is rejected we might need to resort particles according to the loaded configurations cells_resort_particles(CELL_GLOBAL_EXCHANGE); invalidate_obs(); if (ghmc_mflip == GHMC_MFLIP_ON) { momentum_flip(); } else if (ghmc_mflip == GHMC_MFLIP_RAND) { if (d_random() < 0.5) momentum_flip(); } } //fprintf(stderr,"%d: temp after mc: %f\n",this_node,calc_local_temp()); }
/** Computes the FENE pair force and adds this force to the particle forces (see \ref interaction_data.cpp). @param p1 Pointer to first particle. @param p2 Pointer to second/middle particle. @param iaparams bond type number of the angle interaction (see \ref interaction_data.cpp). @param dx particle distance vector @param force returns force of particle 1 @return true if the bond is broken */ inline int calc_fene_pair_force(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, double dx[3], double force[3]) { int i; double fac, dr, len2, len; len2 = sqrlen(dx); len = sqrt(len2); dr = len - iaparams->p.fene.r0; if(dr >= iaparams->p.fene.drmax) return 1; fac = -iaparams->p.fene.k * dr / ((1.0 - dr*dr*iaparams->p.fene.drmax2i)); if (fabs(dr) > ROUND_ERROR_PREC) { if(len > ROUND_ERROR_PREC) { /* Regular case */ fac /= len ; } else { /* dx[] == 0: the force is undefined. Let's use a random direction */ for(i=0;i<3;i++) dx[i] = d_random()-0.5; fac /= sqrt(sqrlen(dx)); } } else { fac = 0.0; } FENE_TRACE(if(fac > 50) fprintf(stderr,"WARNING: FENE force factor between Pair (%d,%d) large: %f at distance %f\n", p1->p.identity,p2->p.identity,fac,sqrt(len2)) ); for(i=0;i<3;i++) force[i] = fac*dx[i]; ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: FENE f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,sqrt(len2),fac)); ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: FENE f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,sqrt(len2),fac)); return 0; }
/** Computes the QUARTIC pair force and adds this force to the particle forces (see \ref interaction_data.cpp). @param p1 Pointer to first particle. @param p2 Pointer to second/middle particle. @param iaparams bond type number of the angle interaction (see \ref interaction_data.cpp). @param dx particle distance vector @param force returns force of particle 1 @return 0. */ inline int calc_quartic_pair_force(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, double dx[3], double force[3]) { int i; double fac; double dist2 = sqrlen(dx); double dist = sqrt(dist2); double dr; if ((iaparams->p.quartic.r_cut > 0.0) && (dist > iaparams->p.quartic.r_cut)) return 1; dr = dist - iaparams->p.quartic.r; if (fabs(dr) > ROUND_ERROR_PREC) { if(dist>ROUND_ERROR_PREC) { /* Regular case */ fac = dr / dist; } else { /* dx[] == 0: the force is undefined. Let's use a random direction */ for(i=0;i<3;i++) dx[i] = d_random()-0.5; fac = dr / sqrt(sqrlen(dx)); } } else { fac=0; } for(i=0;i<3;i++) force[i] = -(iaparams->p.quartic.k0 + iaparams->p.quartic.k1 * dr * dr ) * fac*dx[i]; ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: QUARTIC f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist2,fac)); ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: QUARTIC f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist2,fac)); return 0; }
double maxwell_velocitiesC(int part_id, int N_T) { double v[3], v_av[3],uniran[2]; int i; int flag=1; uniran[0]=d_random(); uniran[1]=d_random(); v_av[0] = v_av[1] = v_av[2] = 0.0; for (i=part_id; i < part_id+N_T; i++) { if(flag == 1 ) { v[0] = pow((-2. * log(uniran[0])),0.5) * cos (2. * PI * uniran[1]) * time_step; v[1] = pow((-2. * log(uniran[1])),0.5) * sin (2. * PI * uniran[0]) * time_step; uniran[0]=d_random(); uniran[1]=d_random(); v[2] = pow((-2. * log(uniran[0])),0.5) * cos (2. * PI * uniran[1]) * time_step; flag = 0; } else { v[0] = pow((-2. * log(uniran[1])),0.5) * sin (2. * PI * uniran[0]) * time_step; uniran[0]=d_random(); uniran[1]=d_random(); v[1] = pow((-2. * log(uniran[0])),0.5) * cos (2. * PI * uniran[1]) * time_step; v[2] = pow((-2. * log(uniran[1])),0.5) * sin (2. * PI * uniran[0]) * time_step; flag = 1; } //printf("%f \n %f \n %f \n",v[0],v[1],v[2]); v_av[0]+=v[0]; v_av[1]+=v[1]; v_av[2]+=v[2]; if (set_particle_v(i, v)==ES_ERROR) { fprintf(stderr, "INTERNAL ERROR: failed upon setting one of the velocities in Espresso (current average: %f)!\n",sqrt(SQR(v_av[0])+SQR(v_av[1])+SQR(v_av[2]))); fprintf(stderr, "Aborting...\n"); errexit(); } } // note that time_step == -1, as long as it is not yet set return ( sqrt(SQR(v_av[0])+SQR(v_av[1])+SQR(v_av[2])) / fabs(time_step) ); }
/** Generator for Gaussian random numbers. Uses the Box-Muller * transformation to generate two Gaussian random numbers from two * uniform random numbers. * * @return Gaussian random number. * */ inline double gaussian_random(void) { double x1, x2, r2, fac; static int calc_new = 1; static double save; /* On every second call two gaussian random numbers are calculated via the Box-Muller transformation. One is returned as the result and the second one is stored for use on the next call. */ if (calc_new) { /* draw two uniform random numbers in the unit circle */ do { x1 = 2.0*d_random()-1.0; x2 = 2.0*d_random()-1.0; r2 = x1*x1 + x2*x2; } while (r2 >= 1.0 || r2 == 0.0); /* perform Box-Muller transformation */ fac = sqrt(-2.0*log(r2)/r2); /* save one number for later use */ save = x1*fac; calc_new = 0; /* return the second number */ return x2*fac; } else { calc_new = 1; /* return the stored gaussian random number */ return save; } }
double velocitiesC(double v_max, int part_id, int N_T) { double v[3], v_av[3]; int i; v_av[0] = v_av[1] = v_av[2] = 0.0; for (i=part_id; i < part_id+N_T; i++) { do { v[0] = v_max * 2.*(d_random()-.5) * time_step; v[1] = v_max * 2.*(d_random()-.5) * time_step; v[2] = v_max * 2.*(d_random()-.5) * time_step; // note that time_step == -1, as long as it is not yet set } while ( sqrt(SQR(v[0])+SQR(v[1])+SQR(v[2])) > v_max * fabs(time_step)); v_av[0]+=v[0]; v_av[1]+=v[1]; v_av[2]+=v[2]; if (set_particle_v(i, v)==ES_ERROR) { fprintf(stderr, "INTERNAL ERROR: failed upon setting one of the velocities in Espresso (current average: %f)!\n", sqrt(SQR(v_av[0])+SQR(v_av[1])+SQR(v_av[2]))); fprintf(stderr, "Aborting...\n"); errexit(); } } // note that time_step == -1, as long as it is not yet set return ( sqrt(SQR(v_av[0])+SQR(v_av[1])+SQR(v_av[2])) / fabs(time_step) ); }
int counterionsC(int N_CI, int part_id, int mode, double shield, int max_try, double val_CI, int type_CI) { int n, cnt1,max_cnt; double pos[3]; cnt1 = max_cnt = 0; for (n=0; n<N_CI; n++) { for (cnt1=0; cnt1<max_try; cnt1++) { pos[0]=box_l[0]*d_random(); pos[1]=box_l[1]*d_random(); pos[2]=box_l[2]*d_random(); if ((mode!=0) || (collision(pos, shield, 0, NULL)==0)) break; POLY_TRACE(printf("c"); fflush(NULL)); } if (cnt1 >= max_try) return (-1); if (place_particle(part_id, pos)==ES_PART_ERROR) return (-3); if (set_particle_q(part_id, val_CI)==ES_ERROR) return (-3); if (set_particle_type(part_id, type_CI)==ES_ERROR) return (-3); part_id++; max_cnt=imax(cnt1, max_cnt); POLY_TRACE(printf("C"); fflush(NULL)); } POLY_TRACE(printf(" %d->%d \n",cnt1,max_cnt)); if (cnt1 >= max_try) return(-1); return(imax(max_cnt,cnt1)); }
/** Computes the HARMONIC pair force and adds this force to the particle forces (see \ref interaction_data.cpp). @param p1 Pointer to first particle. @param p2 Pointer to second/middle particle. @param iaparams bond type number of the angle interaction (see \ref interaction_data.cpp). @param dx particle distance vector @param force returns force of particle 1 @return 0. */ inline int calc_harmonic_pair_force(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, double dx[3], double force[3]) { int i; double fac; double dist2 = sqrlen(dx); double dist = sqrt(dist2); double dr; if ((iaparams->p.harmonic.r_cut > 0.0) && (dist > iaparams->p.harmonic.r_cut)) return 1; dr = dist - iaparams->p.harmonic.r; fac = -iaparams->p.harmonic.k * dr; if (fabs(dr) > ROUND_ERROR_PREC) { if(dist>ROUND_ERROR_PREC) { /* Regular case */ fac /= dist; } else { /* dx[] == 0: the force is undefined. Let's use a random direction */ for(i=0;i<3;i++) dx[i] = d_random()-0.5; fac /= sqrt(sqrlen(dx)); } } else { fac=0; } for(i=0;i<3;i++) force[i] = fac*dx[i]; ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: HARMONIC f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist2,fac)); ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: HARMONIC f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist2,fac)); #ifdef CONFIGTEMP extern double configtemp[2]; int numfac = 0; if (p1->p.configtemp) numfac+=1; if (p2->p.configtemp) numfac+=1; configtemp[0] += numfac*SQR(iaparams->p.harmonic.k * dr); configtemp[1] -= numfac*iaparams->p.harmonic.k*(3-2.*iaparams->p.harmonic.r/dist); #endif return 0; }
/** Implementation of the tcl-command t_random [{ int \<n\> | seed [\<seed(0)\> ... \<seed(n_nodes-1)\>] | stat [status-list] }] <ul> <li> Without further arguments, it returns a random double between 0 and 1. <li> If 'int \<n\>' is given, it returns a random integer between 0 and n-1. <li> If 'seed'/'stat' is given without further arguments, it returns a tcl-list with the current seeds/status of the n_nodes active nodes; otherwise it issues the given parameters as the new seeds/status to the respective nodes. </ul> */ int tclcommand_t_random (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char buffer[100 + TCL_DOUBLE_SPACE + 3*TCL_INTEGER_SPACE]; if (argc == 1) { /* 't_random' */ sprintf(buffer, "%f", d_random()); Tcl_AppendResult(interp, buffer, (char *) NULL); return (TCL_OK); } /* argc > 1 */ argc--; argv++; if ( ARG_IS_S(0,"int") ) /* 't_random int <n>' */ { if(argc < 2) { Tcl_AppendResult(interp, "\nWrong # of args: Usage: 't_random int <n>'", (char *) NULL); return (TCL_ERROR); } else { int i_max; if( !ARG_IS_I(1,i_max) ) { Tcl_AppendResult(interp, "\nWrong type: Usage: 't_random int <n>'", (char *) NULL); return (TCL_ERROR); } sprintf(buffer, "%d", i_random(i_max)); Tcl_AppendResult(interp, buffer, (char *) NULL); return (TCL_OK); } } else if ( ARG_IS_S(0,"stat") ) { if(argc == 1) { Tcl_AppendResult(interp, Random::mpi_random_get_stat().c_str(), nullptr); return TCL_OK; } else { auto error_msg = [interp]() { Tcl_AppendResult(interp, "\nWrong # of args: Usage: 't_random stat \"<state(1)> ... <state(n_nodes*625)>\"'", (char *) NULL); }; if(argc != 2) { error_msg(); return TCL_ERROR; } std::vector<std::string> states(n_nodes); std::istringstream iss(argv[1]); std::string tmp; /** Argument counter to check that the caller provided enough numbers. */ int n_args = 0; for(int node = 0; (node < n_nodes) && std::getline(iss, tmp, ' '); node++) { n_args++; /** First one is handled different, because of the space */ states[node] = tmp; for(int i = 0; (i < 624) && std::getline(iss, tmp, ' '); i++) { n_args++; states[node].append(" "); states[node].append(tmp); } } if(n_args == n_nodes*625) { Random::mpi_random_set_stat(states); return TCL_OK; } else { error_msg(); return TCL_ERROR; } } } else if ( ARG_IS_S(0,"seed") ) /* 't_random seed [<seed(0)> ... <seed(n_nodes-1)>]' */ { std::vector<int> seeds(n_nodes); if ((argc > 1) && (argc < n_nodes+1)) /* Fewer seeds than nodes */ { sprintf(buffer, "Wrong # of args (%d)! Usage: 't_random seed [<seed(0)> ... <seed(%d)>]'", argc,n_nodes-1); Tcl_AppendResult(interp, buffer, (char *)NULL); return (TCL_ERROR); } if (argc <= 1) { std::iota(seeds.begin(), seeds.end(), 1); for(auto &seed: seeds) { sprintf(buffer, "%d ", seed); Tcl_AppendResult(interp, buffer, (char *) NULL); } } else /* Get seeds for different nodes */ { for (int i = 0; i < n_nodes; i++) { if( !ARG_IS_I(i+1,seeds[i]) ) { sprintf(buffer, "\nWrong type for seed %d:\nUsage: 't_random seed [<seed(0)> ... <seed(%d)>]'", i+1 ,n_nodes-1); Tcl_AppendResult(interp, buffer, (char *)NULL); return (TCL_ERROR); } } } #ifdef RANDOM_TRACE printf("Got "); for(int i=0;i<n_nodes;i++) printf("%d ",seeds[i]); printf("as new seeds.\n"); #endif Random::mpi_random_seed(n_nodes,seeds); return(TCL_OK); } /* else */ sprintf(buffer, "Usage: 't_random [{ int <n> | seed [<seed(0)> ... <seed(%d)>] }]'",n_nodes-1); Tcl_AppendResult(interp, "Unknown argument '",argv[0],"' requested!\n",buffer, (char *)NULL); return (TCL_ERROR); }
inline int calc_drude_forces(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, double dx[3], double force1[3], double force2[3]) { int dummy,i; double dist2 = sqrlen(dx); double dist = sqrt(dist2); if ((iaparams->p.drude.r_cut > 0.0) && (dist > iaparams->p.drude.r_cut)) return 1; double force_harmonic[3] = {0., 0., 0.}; double force_subt_elec[3] = {0., 0., 0.}; double force_lv_com[3] = {0., 0., 0.}; double force_lv_dist[3] = {0., 0., 0.}; double chgfac = p1->p.q*p2->p.q; double fac_harmonic = -iaparams->p.drude.k; double gamma_c = iaparams->p.drude.gamma_core; double gamma_d = iaparams->p.drude.gamma_drude; double temp_c = iaparams->p.drude.temp_core; double temp_d = iaparams->p.drude.temp_drude; double mass_c = p1->p.mass; double mass_d = p2->p.mass; double mass_tot = mass_d + mass_c; double mass_tot_inv = 1.0 / mass_tot; double mass_red = mass_d * mass_c / mass_tot; double mass_red_inv = 1.0 / mass_red; //double rnd_c[3] = { (d_random()-0.5), (d_random()-0.5), (d_random()-0.5) }; //double rnd_d[3] = { (d_random()-0.5), (d_random()-0.5), (d_random()-0.5) }; for (i=0;i<3;i++) { double com_vel = mass_tot_inv * (mass_c * p1->m.v[i] + mass_d * p2->m.v[i]); //force_lv_com[i] = -gamma_c / time_step * com_vel + sqrt(24.0 * gamma_c / time_step * temp_c) * (d_random()-0.5); force_lv_com[i] = -gamma_c / time_step * com_vel + sqrt(2.0 * gamma_c / time_step * temp_c) * gaussian_random(); double dist_vel = p2->m.v[i] - p1->m.v[i]; //force_lv_dist[i] = -gamma_d / time_step * dist_vel + sqrt(24.0 * gamma_d / time_step * temp_d) * (d_random()-0.5); force_lv_dist[i] = -gamma_d / time_step * dist_vel + sqrt(2.0 * gamma_d / time_step * temp_d) * gaussian_random(); } /* Apply forces: -Harmonic bond -Langevin thermostat on distance core-drude and com in lab coords result in cross terms for velocities and rnd kicks */ if (dist<ROUND_ERROR_PREC) { /* dx[] == 0: the force is undefined. Let's use a random direction and no spring */ for(i=0;i<3;i++) { dx[i] = d_random()-0.5; } dist2 = sqrlen(dx); dist = sqrt(dist2); fac_harmonic = 0; fprintf(stderr,"dist<ROUND_ERROR_PREC"); } for (i=0;i<3;i++) { force_harmonic[i] = fac_harmonic*dx[i]; force1[i] = mass_c * mass_tot_inv * force_lv_com[i] - force_lv_dist[i] + force_harmonic[i]; //Core force2[i] = mass_d * mass_tot_inv * force_lv_com[i] + force_lv_dist[i] - force_harmonic[i]; //Drude //force_subt_elec[i] = -coulomb.prefactor * chgfac * dx[i] / dist / dist2; //force1[i] = mass_c * mass_tot_inv * force_lv_com[i] - force_lv_dist[i] + force_harmonic[i] + force_subt_elec[i]; //Core //force2[i] = mass_d * mass_tot_inv * force_lv_com[i] + force_lv_dist[i] - force_harmonic[i] - force_subt_elec[i]; //Drude //force1[i] = force_com[i] + force_harmonic[i] + force_subt_elec[i]; //Core //force2[i] = force_com[i] - force_harmonic[i] - force_subt_elec[i]; //Drude } //fprintf(stderr,"Core Tot: %g %g %g\n", force1[0],force1[1],force1[2]); //fprintf(stderr,"Drude Tot: %g %g %g\n", force2[0],force2[1],force2[2]); /* fprintf(stderr,"\ndx: %g %g %g\n", dx[0],dx[1],dx[2]); fprintf(stderr,"dv: %g %g %g\n", p2->m.v[0] - p1->m.v[0],p2->m.v[1] - p1->m.v[1],p2->m.v[2] - p1->m.v[2]); fprintf(stderr,"Harmonic: %g %g %g\n", force_harmonic[0],force_harmonic[1],force_harmonic[2]); fprintf(stderr,"Subt_elec: %g %g %g\n", force_subt_elec[0],force_subt_elec[1],force_subt_elec[2]); fprintf(stderr,"Dist: %g %g %g\n", force_lv_dist[0],force_lv_dist[1],force_lv_dist[2]); fprintf(stderr,"Com: %g %g %g\n", force_lv_com[0],force_lv_com[1],force_lv_com[2]); fprintf(stderr,"Core Tot: %g %g %g\n", force1[0],force1[1],force1[2]); fprintf(stderr,"Drude Tot: %g %g %g\n", force2[0],force2[1],force2[2]); */ ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: DRUDE f = (%.3e,%.3e,%.3e)\n",this_node,p1->f.f[0]+force1[0],p1->f.f[1]+force1[1],p1->f.f[2]+force1[2])); ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: DRUDE f = (%.3e,%.3e,%.3e)\n",this_node,p2->f.f[0]+force2[0],p2->f.f[1]+force2[1],p2->f.f[2]+force2[2])); return 0; }
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; } } }
void integrate_reaction() { int c, np, n, i; Particle * p1, *p2, **pairs; Cell * cell; double dist2, vec21[3], rand; if(reaction.rate > 0) { int reactants = 0, products = 0; int tot_reactants = 0, tot_products = 0; double ratexp, back_ratexp; ratexp = exp(-time_step*reaction.rate); on_observable_calc(); for (c = 0; c < local_cells.n; c++) { /* Loop cell neighbors */ for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { pairs = dd.cell_inter[c].nList[n].vList.pair; np = dd.cell_inter[c].nList[n].vList.n; /* verlet list loop */ for(i = 0; i < 2 * np; i += 2) { p1 = pairs[i]; //pointer to particle 1 p2 = pairs[i+1]; //pointer to particle 2 if( (p1->p.type == reaction.reactant_type && p2->p.type == reaction.catalyzer_type) || (p2->p.type == reaction.reactant_type && p1->p.type == reaction.catalyzer_type) ) { get_mi_vector(vec21, p1->r.p, p2->r.p); dist2 = sqrlen(vec21); if(dist2 < reaction.range * reaction.range) { rand = d_random(); if(rand > ratexp) { if(p1->p.type == reaction.reactant_type) { p1->p.type = reaction.product_type; } else { p2->p.type = reaction.product_type; } } } } } } } if (reaction.back_rate < 0) { // we have to determine it dynamically /* we count now how many reactants and products are in the sim box */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p1 = cell->part; np = cell->n; for(i = 0; i < np; i++) { if(p1[i].p.type == reaction.reactant_type) reactants++; else if(p1[i].p.type == reaction.product_type) products++; } } MPI_Allreduce(&reactants, &tot_reactants, 1, MPI_INT, MPI_SUM, comm_cart); MPI_Allreduce(&products, &tot_products, 1, MPI_INT, MPI_SUM, comm_cart); back_ratexp = ratexp * tot_reactants / tot_products ; //with this the asymptotic ratio reactant/product becomes 1/1 and the catalyzer volume only determines the time that it takes to reach this } else { //use the back reaction rate supplied by the user back_ratexp = exp(-time_step*reaction.back_rate); } if(back_ratexp < 1 ) { for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p1 = cell->part; np = cell->n; for(i = 0; i < np; i++) { if(p1[i].p.type == reaction.product_type) { rand = d_random(); if(rand > back_ratexp) { printf("DEBUG: integrate_reaction; back_react\n"); //TODO delete p1[i].p.type=reaction.reactant_type; } } } } } on_particle_change(); } }
int saltC(int N_pS, int N_nS, int part_id, int mode, double shield, int max_try, double val_pS, double val_nS, int type_pS, int type_nS, double rad) { int n, cnt1,max_cnt; double pos[3], dis2; cnt1 = max_cnt = 0; /* Place positive salt ions */ for (n=0; n<N_pS; n++) { for (cnt1=0; cnt1<max_try; cnt1++) { if (rad > 0.) { pos[0]=rad*(2.*d_random()-1.); pos[1]=rad*(2.*d_random()-1.); pos[2]=rad*(2.*d_random()-1.); dis2 = pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]; pos[0] += box_l[0]*0.5; pos[1] += box_l[1]*0.5; pos[2] += box_l[2]*0.5; if (((mode!=0) || (collision(pos, shield, 0, NULL)==0)) && (dis2 < (rad * rad))) break; } else { pos[0]=box_l[0]*d_random(); pos[1]=box_l[1]*d_random(); pos[2]=box_l[2]*d_random(); if ((mode!=0) || (collision(pos, shield, 0, NULL)==0)) break; } POLY_TRACE(printf("p"); fflush(NULL)); } if (cnt1 >= max_try) return (-1); if (place_particle(part_id, pos)==ES_PART_ERROR) return (-3); if (set_particle_q(part_id, val_pS)==ES_ERROR) return (-3); if (set_particle_type(part_id, type_pS)==ES_ERROR) return (-3); part_id++; max_cnt=imax(cnt1, max_cnt); POLY_TRACE(printf("P"); fflush(NULL)); } POLY_TRACE(printf(" %d->%d \n",cnt1,max_cnt)); if (cnt1 >= max_try) return(-1); /* Place negative salt ions */ for (n=0; n<N_nS; n++) { for (cnt1=0; cnt1<max_try; cnt1++) { if (rad > 0.) { pos[0]=rad*(2.*d_random()-1.); pos[1]=rad*(2.*d_random()-1.); pos[2]=rad*(2.*d_random()-1.); dis2 = pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]; pos[0] += box_l[0]*0.5; pos[1] += box_l[1]*0.5; pos[2] += box_l[2]*0.5; if (((mode!=0) || (collision(pos, shield, 0, NULL)==0)) && (dis2 < (rad * rad))) break; } else { pos[0]=box_l[0]*d_random(); pos[1]=box_l[1]*d_random(); pos[2]=box_l[2]*d_random(); if ((mode!=0) || (collision(pos, shield, 0, NULL)==0)) break; } POLY_TRACE(printf("n"); fflush(NULL)); } if (cnt1 >= max_try) return (-1); if (place_particle(part_id, pos)==ES_PART_ERROR) return (-3); if (set_particle_q(part_id, val_nS)==ES_ERROR) return (-3); if (set_particle_type(part_id, type_nS)==ES_ERROR) return (-3); part_id++; max_cnt=imax(cnt1, max_cnt); POLY_TRACE(printf("N"); fflush(NULL)); } POLY_TRACE(printf(" %d->%d \n",cnt1,max_cnt)); if (cnt1 >= max_try) return(-2); return(imax(max_cnt,cnt1)); }
/** Generator for Gaussian random numbers. Uses the Box-Muller * transformation to generate two Gaussian random numbers from two * uniform random numbers. which generates numbers between -2 sigma and 2 sigma in the form of a Gaussian with standard deviation sigma=1.118591404 resulting in * an actual standard deviation of 1. * * @return Gaussian random number. * */ inline double gaussian_random_cut(void) { double x1, x2, r2, fac; static int calc_new = 1; static double save, curr; /* On every second call two gaussian random numbers are calculated via the Box-Muller transformation. One is returned as the result and the second one is stored for use on the next call. */ if (calc_new) { /* draw two uniform random numbers in the unit circle */ do { x1 = 2.0*d_random()-1.0; x2 = 2.0*d_random()-1.0; r2 = x1*x1 + x2*x2; } while (r2 >= 1.0 || r2 == 0.0); /* perform Box-Muller transformation */ fac = sqrt(-2.0*log(r2)/r2); // save one number for later use save = x1*fac*1.042267973; if ( fabs(save) > 2*1.042267973 ) { if ( save > 0 ) save = 2*1.042267973; else save = -2*1.042267973; } calc_new = 0; // return the second number curr = x2*fac*1.042267973; if ( fabs(curr) > 2*1.042267973) { if ( curr > 0 ) curr = 2*1.042267973; else curr = -2*1.042267973; } return curr; /* save one number for later use */ /* save = x1*fac*1.118591404; if ( fabs(save) > 2*1.118591404 ) { save = (2.0*d_random()-1.0)*2*1.118591404; } calc_new = 0; // return the second number curr = x2*fac*1.118591404; if ( fabs(curr) > 2*1.118591404) { curr = (2.0*d_random()-1.0)*2*1.118591404; } return curr; */ } else { calc_new = 1; /* return the stored gaussian random number */ return save; } }
/** 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 }
/** Implementation of the tcl-command t_random [{ int \<n\> | seed [\<seed(0)\> ... \<seed(n_nodes-1)\>] | stat [status-list] }] <ul> <li> Without further arguments, it returns a random double between 0 and 1. <li> If 'int \<n\>' is given, it returns a random integer between 0 and n-1. <li> If 'seed'/'stat' is given without further arguments, it returns a tcl-list with the current seeds/status of the n_nodes active nodes; otherwise it issues the given parameters as the new seeds/status to the respective nodes. </ul> */ int tclcommand_t_random (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char buffer[100 + TCL_DOUBLE_SPACE + 3*TCL_INTEGER_SPACE]; int i,j,cnt, i_out, temp; double d_out; if (argc == 1) { /* 't_random' */ d_out = d_random(); sprintf(buffer, "%f", d_out); Tcl_AppendResult(interp, buffer, (char *) NULL); return (TCL_OK); } /* argc > 1 */ argc--; argv++; if ( ARG_IS_S(0,"int") ) /* 't_random int <n>' */ { if(argc < 2) { Tcl_AppendResult(interp, "\nWrong # of args: Usage: 't_random int <n>'", (char *) NULL); return (TCL_ERROR); } else { if( !ARG_IS_I(1,i_out) ) { Tcl_AppendResult(interp, "\nWrong type: Usage: 't_random int <n>'", (char *) NULL); return (TCL_ERROR); } i_out = i_random(i_out); sprintf(buffer, "%d", i_out); Tcl_AppendResult(interp, buffer, (char *) NULL); return (TCL_OK); } } else if ( ARG_IS_S(0,"seed") ) /* 't_random seed [<seed(0)> ... <seed(n_nodes-1)>]' */ { long *seed = (long *) malloc(n_nodes*sizeof(long)); if (argc <= 1) /* ESPResSo generates a seed */ { mpi_random_seed(0,seed); for (i=0; i < n_nodes; i++) { sprintf(buffer, "%ld ", seed[i]); Tcl_AppendResult(interp, buffer, (char *) NULL); } } else if (argc < n_nodes+1) /* Fewer seeds than nodes */ { sprintf(buffer, "Wrong # of args (%d)! Usage: 't_random seed [<seed(0)> ... <seed(%d)>]'", argc,n_nodes-1); Tcl_AppendResult(interp, buffer, (char *)NULL); return (TCL_ERROR); } else /* Get seeds for different nodes */ { for (i=0; i < n_nodes; i++) { if( !ARG_IS_I(i+1,temp) ) { sprintf(buffer, "\nWrong type for seed %d:\nUsage: 't_random seed [<seed(0)> ... <seed(%d)>]'", i+1 ,n_nodes-1); Tcl_AppendResult(interp, buffer, (char *)NULL); return (TCL_ERROR); } else { seed[i] = (long)temp; } } RANDOM_TRACE( printf("Got "); for(i=0;i<n_nodes;i++) printf("%ld ",seed[i]); printf("as new seeds.\n") ); mpi_random_seed(n_nodes,seed); } free(seed); return(TCL_OK); }
void integrate_vv(int n_steps) { int i; #ifdef REACTIONS int c, np, n; Particle * p1, *p2, **pairs; Cell * cell; double dist2, vec21[3], rand; if(reaction.rate > 0) { int reactants = 0, products = 0; int tot_reactants = 0, tot_products = 0; double ratexp, back_ratexp; ratexp = exp(-time_step*reaction.rate); on_observable_calc(); for (c = 0; c < local_cells.n; c++) { /* Loop cell neighbors */ for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { pairs = dd.cell_inter[c].nList[n].vList.pair; np = dd.cell_inter[c].nList[n].vList.n; /* verlet list loop */ for(i = 0; i < 2 * np; i += 2) { p1 = pairs[i]; //pointer to particle 1 p2 = pairs[i+1]; //pointer to particle 2 if( (p1->p.type == reaction.reactant_type && p2->p.type == reaction.catalyzer_type) || (p2->p.type == reaction.reactant_type && p1->p.type == reaction.catalyzer_type) ) { get_mi_vector(vec21, p1->r.p, p2->r.p); dist2 = sqrlen(vec21); if(dist2 < reaction.range * reaction.range) { rand =d_random(); if(rand > ratexp) { if(p1->p.type==reaction.reactant_type) { p1->p.type = reaction.product_type; } else { p2->p.type = reaction.product_type; } } } } } } } if (reaction.back_rate < 0) { // we have to determine it dynamically /* we count now how many reactants and products are in the sim box */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p1 = cell->part; np = cell->n; for(i = 0; i < np; i++) { if(p1[i].p.type == reaction.reactant_type) reactants++; else if(p1[i].p.type == reaction.product_type) products++; } } MPI_Allreduce(&reactants, &tot_reactants, 1, MPI_INT, MPI_SUM, comm_cart); MPI_Allreduce(&products, &tot_products, 1, MPI_INT, MPI_SUM, comm_cart); back_ratexp = ratexp * tot_reactants / tot_products ; //with this the asymptotic ratio reactant/product becomes 1/1 and the catalyzer volume only determines the time that it takes to reach this } else { //use the back reaction rate supplied by the user back_ratexp = exp(-time_step*reaction.back_rate); } if(back_ratexp < 1 ) { for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p1 = cell->part; np = cell->n; for(i = 0; i < np; i++) { if(p1[i].p.type == reaction.product_type) { rand = d_random(); if(rand > back_ratexp) { p1[i].p.type=reaction.reactant_type; } } } } } on_particle_change(); } #endif /* ifdef REACTIONS */ /* Prepare the Integrator */ on_integration_start(); /* if any method vetoes (P3M not initialized), immediately bail out */ if (check_runtime_errors()) return; /* Verlet list criterion */ skin2 = SQR(0.5 * skin); INTEG_TRACE(fprintf(stderr,"%d: integrate_vv: integrating %d steps (recalc_forces=%d)\n", this_node, n_steps, recalc_forces)); /* Integration Step: Preparation for first integration step: Calculate forces f(t) as function of positions p(t) ( and velocities v(t) ) */ if (recalc_forces) { thermo_heat_up(); #ifdef LB transfer_momentum = 0; #endif #ifdef LB_GPU transfer_momentum_gpu = 0; #endif //VIRTUAL_SITES pos (and vel for DPD) update for security reason !!! #ifdef VIRTUAL_SITES update_mol_vel_pos(); ghost_communicator(&cell_structure.update_ghost_pos_comm); if (check_runtime_errors()) return; #ifdef ADRESS // adress_update_weights(); if (check_runtime_errors()) return; #endif #endif #ifdef COLLISION_DETECTION prepare_collision_queue(); #endif force_calc(); //VIRTUAL_SITES distribute forces #ifdef VIRTUAL_SITES ghost_communicator(&cell_structure.collect_ghost_force_comm); init_forces_ghosts(); distribute_mol_force(); if (check_runtime_errors()) return; #endif ghost_communicator(&cell_structure.collect_ghost_force_comm); #ifdef ROTATION convert_initial_torques(); #endif thermo_cool_down(); /* Communication Step: ghost forces */ /*apply trap forces to trapped molecules*/ #ifdef MOLFORCES calc_and_apply_mol_constraints(); #endif rescale_forces(); recalc_forces = 0; #ifdef COLLISION_DETECTION handle_collisions(); #endif } if (check_runtime_errors()) return; n_verlet_updates = 0; /* Integration loop */ for(i=0;i<n_steps;i++) { INTEG_TRACE(fprintf(stderr,"%d: STEP %d\n",this_node,i)); #ifdef BOND_CONSTRAINT save_old_pos(); #endif /* Integration Steps: Step 1 and 2 of Velocity Verlet scheme: v(t+0.5*dt) = v(t) + 0.5*dt * f(t) p(t + dt) = p(t) + dt * v(t+0.5*dt) NOTE 1: Prefactors do not occur in formulas since we use rescaled forces and velocities. NOTE 2: Depending on the integration method Step 1 and Step 2 cannot be combined for the translation. */ if(integ_switch == INTEG_METHOD_NPT_ISO || nemd_method != NEMD_METHOD_OFF) { propagate_vel(); propagate_pos(); } else propagate_vel_pos(); #ifdef BOND_CONSTRAINT /**Correct those particle positions that participate in a rigid/constrained bond */ cells_update_ghosts(); correct_pos_shake(); #endif #ifdef ELECTROSTATICS if(coulomb.method == COULOMB_MAGGS) { maggs_propagate_B_field(0.5*time_step); } #endif #ifdef NPT if (check_runtime_errors()) break; #endif cells_update_ghosts(); //VIRTUAL_SITES update pos and vel (for DPD) #ifdef VIRTUAL_SITES update_mol_vel_pos(); ghost_communicator(&cell_structure.update_ghost_pos_comm); if (check_runtime_errors()) break; #if defined(VIRTUAL_SITES_RELATIVE) && defined(LB) // This is on a workaround stage: // When using virtual sites relative and LB at the same time, it is necessary // to reassemble the cell lists after all position updates, also of virtual // particles. if (cell_structure.type == CELL_STRUCTURE_DOMDEC && (!dd.use_vList) ) cells_update_ghosts(); #endif #ifdef ADRESS //adress_update_weights(); if (check_runtime_errors()) break; #endif #endif /* Integration Step: Step 3 of Velocity Verlet scheme: Calculate f(t+dt) as function of positions p(t+dt) ( and velocities v(t+0.5*dt) ) */ #ifdef LB transfer_momentum = 1; #endif #ifdef LB_GPU transfer_momentum_gpu = 1; #endif #ifdef COLLISION_DETECTION prepare_collision_queue(); #endif force_calc(); //VIRTUAL_SITES distribute forces #ifdef VIRTUAL_SITES ghost_communicator(&cell_structure.collect_ghost_force_comm); init_forces_ghosts(); distribute_mol_force(); if (check_runtime_errors()) break; #endif /* Communication step: ghost forces */ ghost_communicator(&cell_structure.collect_ghost_force_comm); /*apply trap forces to trapped molecules*/ #ifdef MOLFORCES calc_and_apply_mol_constraints(); #endif if (check_runtime_errors()) break; /* Integration Step: Step 4 of Velocity Verlet scheme: v(t+dt) = v(t+0.5*dt) + 0.5*dt * f(t+dt) */ rescale_forces_propagate_vel(); recalc_forces = 0; #ifdef LB if (lattice_switch & LATTICE_LB) lattice_boltzmann_update(); if (check_runtime_errors()) break; #endif #ifdef LB_GPU if(this_node == 0){ if (lattice_switch & LATTICE_LB_GPU) lattice_boltzmann_update_gpu(); } #endif #ifdef BOND_CONSTRAINT ghost_communicator(&cell_structure.update_ghost_pos_comm); correct_vel_shake(); #endif #ifdef ROTATION convert_torques_propagate_omega(); #endif //VIRTUAL_SITES update vel #ifdef VIRTUAL_SITES ghost_communicator(&cell_structure.update_ghost_pos_comm); update_mol_vel(); if (check_runtime_errors()) break; #endif #ifdef ELECTROSTATICS if(coulomb.method == COULOMB_MAGGS) { maggs_propagate_B_field(0.5*time_step); } #endif #ifdef COLLISION_DETECTION handle_collisions(); #endif #ifdef NPT if((this_node==0) && (integ_switch == INTEG_METHOD_NPT_ISO)) nptiso.p_inst_av += nptiso.p_inst; #endif /* Propagate time: t = t+dt */ sim_time += time_step; } /* verlet list statistics */ if(n_verlet_updates>0) verlet_reuse = n_steps/(double) n_verlet_updates; else verlet_reuse = 0; #ifdef NPT if(integ_switch == INTEG_METHOD_NPT_ISO) { nptiso.invalidate_p_vel = 0; MPI_Bcast(&nptiso.p_inst, 1, MPI_DOUBLE, 0, comm_cart); MPI_Bcast(&nptiso.p_diff, 1, MPI_DOUBLE, 0, comm_cart); MPI_Bcast(&nptiso.volume, 1, MPI_DOUBLE, 0, comm_cart); if(this_node==0) nptiso.p_inst_av /= 1.0*n_steps; MPI_Bcast(&nptiso.p_inst_av, 1, MPI_DOUBLE, 0, comm_cart); } #endif }
/** Calculate soft-sphere potential force between particle p1 and p2 */ inline void add_affinity_pair_force(Particle * p1, Particle * p2, IA_parameters *ia_params, double d[3], double dist, double force[3]) { // The affinity potential has the first argument affinity_type. This is to differentiate between different implementations. For example one implementation can take into account the detachment force, another not. int aff_type_extracted = 0; int period_for_output = -1; if (ia_params->affinity_type > 10 ) { aff_type_extracted = ia_params->affinity_type % 10; period_for_output = ia_params->affinity_type - aff_type_extracted; } else aff_type_extracted = ia_params->affinity_type; if ( aff_type_extracted == 1 ) { /************************ * * Here I can implement the affinity force. * I have the position of the particle - p1, and under p1->p.bond_site I have the coordinate of the bond_site. * Also, under d[3] I have the vector towards the constraint meaning that force on p1 should be in the direction of d[3]. * * Algorithm: * 1. First check is, whether I am in the cut-off radius: ?dist < affinity_cut?. * 2. Then I check whether there exists a bond from the current particle: ?bond_site != -1? * 3. If yes, then I maintain the bond. I put the forces and afterwards I decide whether the bond will brake or not. * 4. If no, I maintain the creation of a bond. First I check whether I am in the area of possible bond creation: ?dist < affinity_r0? * 5. If yes, I run the decision algorithm for bond creation and I either create or does not create the bond. * 6. If I am not in the area of possible bond creation I do nothing * * comments: * strength of the force is proportiona to the difference of actual bond length and relaxed bond length * bond is always created, no probability is involved * if bondlength reaches maxBond, the bond imediately ruptures. No probability is involved *********************/ int j; double fac=0.0; if(CUTOFF_CHECK(dist < ia_params->affinity_cut)) { // Checking whether I am inside the interaction cut-off radius. if(dist > 0.0) { //printf("bond_site: %f %f %f\n",p1->p.bond_site[0],p1->p.bond_site[1],p1->p.bond_site[2]); if ((p1->p.bond_site[0] >= 0) && (p1->p.bond_site[1] >= 0) && (p1->p.bond_site[2] >= 0)) // Checking whether any bond exists { // Bond exists double folded_pos[3], vec[3], len2, len; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); for(j=0;j<3;j++) vec[j] = p1->p.bond_site[j] - folded_pos[j]; // Shouldn't be the vec vector normalized? Yes, but with affinity_r0 and not by len!!! len2 = sqrlen(vec); len = sqrt(len2); if (len > ia_params->affinity_r0) { fac = ia_params->affinity_kappa*(len - ia_params->affinity_r0); //printf("len %f r0 %f\n",len, ia_params->affinity_r0); } else fac = 0.0; // double ftemp = 0; for(j=0;j<3;j++) { force[j] += fac * vec[j] / len; } // printf("%f ",ftemp); // Decision whether I should break the bond: if the bond length is greater than maxBond, it breaks. if (len > ia_params->affinity_maxBond) { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; } } else if (dist < ia_params->affinity_r0) { // Bond does not exist, we are inside of possible bond creation area, lets talk about creating a bond // This implementation creates bond always double folded_pos[3]; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); //printf("d: %f %f %f\n",d[0],d[1],d[2]); for(j=0;j<3;j++) p1->p.bond_site[j] = folded_pos[j] - d[j]; } } } } if ( aff_type_extracted == 2 ) { //second implementation of affinity /************************ * * Here I can implement the affinity force. * I have the position of the particle - p1, and under p1->p.bond_site I have the coordinate of the bond_site. * Also, under d[3] I have the vector towards the constraint meaning that force on p1 should be in the direction of d[3]. * * Algorithm: * 1. First check is whether I am in the cut-off radius: ?dist < affinity_cut?. * 2. Then I check whether there exists a bond from the current particle: ?bond_site != -1? * 3. If yes, then I maintaind the bond. I put the forces and afterwards I decide whether the bond will brake or not. * 4. If no, I maintain the creation of a bond. First I check whether I am in the area of possible bond creation: ?dist < affinity_r0? * 5. If yes, I run the decision algorithm for bond creation and I either create or does not create the bond. * 6. If I am not in the area of possible bond creation I do nothing * * * comments: * strength of the force is proportiona to the difference of actual bond length and relaxed bond length * bond is created with probability 1-exp(-Kon*timestep) * maxBond is not used, we use probability 1-exp(-Koff*timestep) to brake the bond * Koff depends on the bondlenth via Koff = K0*exp(F/Fd) = K0*exp(kappa(r-r0)/Fd) * here, ia_params->Koff gives us K_0, off rate when bond is relaxed. * here, maxBond is used as detachment force F_d. The original check for ensuring, that partice flows out of the cut-off radius and the bond remains active is replaced with fixed check, that bond length must not be greater that 0.8 cut_off *********************/ int j; double fac=0.0; if(CUTOFF_CHECK(dist < ia_params->affinity_cut)) { // Checking whether I am inside the interaction cut-off radius. if(dist > 0.0) { //printf("bond_site: %f %f %f\n",p1->p.bond_site[0],p1->p.bond_site[1],p1->p.bond_site[2]); if ((p1->p.bond_site[0] >= 0) && (p1->p.bond_site[1] >= 0) && (p1->p.bond_site[2] >= 0)) // Checking whether any bond exists { // Bond exists double folded_pos[3], vec[3], len2, len; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); for(j=0;j<3;j++) vec[j] = p1->p.bond_site[j] - folded_pos[j]; // Shouldn't be the vec vector normalized? Yes, but with affinity_r0 and not by len!!! len2 = sqrlen(vec); len = sqrt(len2); if (len > ia_params->affinity_r0) { fac = ia_params->affinity_kappa*(len - ia_params->affinity_r0); //printf("len %f r0 %f\n",len, ia_params->affinity_r0); } else fac = 0.0; //double ftemp = 0; for(j=0;j<3;j++) { force[j] += fac * vec[j] / len; // ftemp += abs(fac * vec[j] / len); } //if (ftemp > 0.000000000000001) printf("%f ",fac); // Decision whether I should break the bond: // First, force exerted on bond is stored in fac double tmpF = fac; // Then, zero force off rate K_0 is stored at ia_params_Koff double tmpK0 = ia_params->affinity_Koff; // Then, detachment force is stored in ia_params->affinity_maxBond double tmpFd = ia_params->affinity_maxBond; // Then, compute Koff double tmpKoff = tmpK0*exp( tmpF / tmpFd); // Finally, compute Poff double Poff = 1.0 - exp( - tmpKoff*time_step); //printf("%f ", Poff); if (len < 0.8*ia_params->affinity_cut) { // in other implementation, maxBond is used here. However, in this implementation, we need maxBond for setting detachment force F_d double decide = d_random(); if ( decide < Poff ) { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; // printf("bond broken. Poff = %f, F = %f, Koff = %f, K0 = %f, len = %f \n",Poff,tmpF,tmpKoff,tmpK0,len); } } else { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; //printf("breaking: out of cut"); } // Checkpoint output: if (period_for_output > 0 ) if (((int)floor(sim_time/time_step) % period_for_output == 0 ) && (len > ia_params->affinity_r0) ) { FILE *fp; double tmpPon = 1.0 - exp( - ia_params->affinity_Kon*time_step); fp = fopen("affinity_check.dat","a"); fprintf(fp,"sim_time %f, period_for_output %d aff type: %d ",sim_time,period_for_output,aff_type_extracted); fprintf(fp,"Pon %f, Kon %f, particle %d, Poff = %f, F = %f, Koff = %f, K0 = %f, len = %f \n",tmpPon, ia_params->affinity_Kon, p1->p.identity, Poff,tmpF,tmpKoff,tmpK0,len); fclose(fp); } } else if (dist < ia_params->affinity_r0) { // Bond does not exist, we are inside of possible bond creation area, lets talk about creating a bond double Pon = 1.0 - exp( - ia_params->affinity_Kon*time_step); // The probability is given by function Pon(x)= 1 - e^(-x) where x is Kon*dt. Here is a table of values of this function, just to have an idea about the values // x | 0 | 0.25 | 0.5 | 0.75 | 1.0 | 1.5 | 2.0 | 3.0 | 5.0 // Pon(x) | 0 | 0.22 | 0.39 | 0.52 | 0.63 | 0.77 | 0.84 | 0.95 | 0.99 double decide = d_random(); if ( decide < Pon ) { // the bond will be created only with probability Pon. //printf("Creating: Pon = %f, decide = %f", Pon, decide); double folded_pos[3]; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); //printf("d: %f %f %f\n",d[0],d[1],d[2]); for(j=0;j<3;j++) p1->p.bond_site[j] = folded_pos[j] - d[j]; } else { //printf("In range, not creating: Pon = %f, decide = %f", Pon, decide); } } } } } if ( aff_type_extracted == 3 ) { /************************ * * Here I can implement the affinity force. * I have the position of the particle - p1, and under p1->p.bond_site I have the coordinate of the bond_site. * Also, under d[3] I have the vector towards the constraint meaning that force on p1 should be in the direction of d[3]. * * Algorithm: * 1. First check is whether I am in the cut-off radius: ?dist < affinity_cut?. * 2. Then I check whether there exists a bond from the current particle: ?bond_site != -1? * 3. If yes, then I maintaind the bond. I put the forces and afterwards I decide whether the bond will brake or not. * 4. If no, I maintain the creation of a bond. First I check whether I am in the area of possible bond creation: ?dist < affinity_r0? * 5. If yes, I run the decision algorithm for bond creation and I either create or does not create the bond. * 6. If I am not in the area of possible bond creation I do nothing * * * comments: * strength of the force is proportiona to the difference of actual bond length and relaxed bond length * bond is created with probability 1-exp(-Kon*timestep) * bond is ruptured with probability 1-exp(-Koff*timestep) to brake the bond * Koff is given as parameter, is not dependent on the force nor the bond length * here, maxBond stands for ensuring, that partice flows out of the cut-off radius and the bond remains active. maxBond should be always less than cut_off radius *********************/ int j; double fac=0.0; if(CUTOFF_CHECK(dist < ia_params->affinity_cut)) { // Checking whether I am inside the interaction cut-off radius. if(dist > 0.0) { //printf("bond_site: %f %f %f\n",p1->p.bond_site[0],p1->p.bond_site[1],p1->p.bond_site[2]); if ((p1->p.bond_site[0] >= 0) && (p1->p.bond_site[1] >= 0) && (p1->p.bond_site[2] >= 0)) // Checking whether any bond exists { // Bond exists double folded_pos[3], vec[3], len2, len; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); for(j=0;j<3;j++) vec[j] = p1->p.bond_site[j] - folded_pos[j]; // Shouldn't be the vec vector normalized? Yes, but with affinity_r0 and not by len!!! len2 = sqrlen(vec); len = sqrt(len2); if (len > ia_params->affinity_r0) { fac = ia_params->affinity_kappa*(len - ia_params->affinity_r0)/len; //printf("len %f r0 %f\n",len, ia_params->affinity_r0); } else fac = 0.0; // double ftemp = 0; for(j=0;j<3;j++) { force[j] += fac * vec[j]; } // printf("%f ",ftemp); // Decision whether I should break the bond: // The random decision algorithm is much more complicated with Fd detachment force etc. Here, I use much simpler rule, the same as with Kon, except that the probability of bond breakage increases with prolongation of the bond. If the bond reaches double Poff = 1.0 - exp( - ia_params->affinity_Koff*time_step); if (len < ia_params->affinity_maxBond) { double decide = d_random(); if ( decide < Poff ) { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; } } else { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; //printf("breaking: out of cut"); } } else if (dist < ia_params->affinity_r0) { // Bond does not exist, we are inside of possible bond creation area, lets talk about creating a bond double Pon = 1.0 - exp( - ia_params->affinity_Kon*time_step); // The probability is given by function Pon(x)= 1 - e^(-x) where x is Kon*dt. Here is a table of values of this function, just to have an idea about the values // x | 0 | 0.25 | 0.5 | 0.75 | 1.0 | 1.5 | 2.0 | 3.0 | 5.0 // Pon(x) | 0 | 0.22 | 0.39 | 0.52 | 0.63 | 0.77 | 0.84 | 0.95 | 0.99 double decide = d_random(); if ( decide < Pon ) { // the bond will be created only with probability Pon. //printf("Creating: Pon = %f, decide = %f", Pon, decide); double folded_pos[3]; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); //printf("d: %f %f %f\n",d[0],d[1],d[2]); for(j=0;j<3;j++) p1->p.bond_site[j] = folded_pos[j] - d[j]; } else { //printf("In range, not creating: Pon = %f, decide = %f", Pon, decide); } } } } } if ( aff_type_extracted == 4 ) { /************************ * * Here I can implement the affinity force. * I have the position of the particle - p1, and under p1->p.bond_site I have the coordinate of the bond_site. * Also, under d[3] I have the vector towards the constraint meaning that force on p1 should be in the direction of d[3]. * * Algorithm: * 1. First check is whether I am in the cut-off radius: ?dist < affinity_cut?. * 2. Then I check whether there exists a bond from the current particle: ?bond_site != -1? * 3. If yes, then I maintaind the bond. I put the forces and afterwards I decide whether the bond will brake or not. * 4. If no, I maintain the creation of a bond. First I check whether I am in the area of possible bond creation: ?dist < affinity_r0? * 5. If yes, I run the decision algorithm for bond creation and I either create or does not create the bond. * 6. If I am not in the area of possible bond creation I do nothing * * * comments: * strength of the force is proportional to the actual bond length * bond is created with probability 1-exp(-Kon*timestep) * maxBond is not used, we use probability 1-exp(-Koff*timestep) to brake the bond * Koff depends on the bondlength via Koff = K0*exp(F/Fd) = K0*exp(kappa*r/Fd) * here, ia_params->Koff gives us K_0, off rate when bond is relaxed. * here, maxBond is used as detachment force F_d. The original check for ensuring, that partice flows out of the cut-off radius and the bond remains active is replaced with fixed check, that bond length must not be greater that 0.8 cut_off *********************/ int j; double fac=0.0; if(CUTOFF_CHECK(dist < ia_params->affinity_cut)) { // Checking whether I am inside the interaction cut-off radius. if(dist > 0.0) { //printf("bond_site: %f %f %f\n",p1->p.bond_site[0],p1->p.bond_site[1],p1->p.bond_site[2]); if ((p1->p.bond_site[0] >= 0) && (p1->p.bond_site[1] >= 0) && (p1->p.bond_site[2] >= 0)) // Checking whether any bond exists { // Bond exists double folded_pos[3], vec[3], len2, len; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); for(j=0;j<3;j++) vec[j] = p1->p.bond_site[j] - folded_pos[j]; // Shouldn't be the vec vector normalized? Yes, but with affinity_r0 and not by len!!! len2 = sqrlen(vec); len = sqrt(len2); fac = ia_params->affinity_kappa*len; //double ftemp = 0; for(j=0;j<3;j++) { force[j] += fac * vec[j] / len; } // Decision whether I should break the bond: // First, force exerted on bond is stored in fac double tmpF = fac; // Then, zero force off rate K_0 is stored at ia_params_Koff double tmpK0 = ia_params->affinity_Koff; // Then, detachment force is stored in ia_params->affinity_maxBond double tmpFd = ia_params->affinity_maxBond; // Then, compute Koff double tmpKoff = tmpK0*exp( tmpF / tmpFd); // Finally, compute Poff double Poff = 1.0 - exp( - tmpKoff*time_step); //printf("%f ", Poff); if (len < 0.8*ia_params->affinity_cut) { // in other implementation, maxBond is used here. However, in this implementation, we need maxBond for setting detachment force F_d double decide = d_random(); if ( decide < Poff ) { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; // printf("bond broken. Poff = %f, F = %f, Koff = %f, K0 = %f, len = %f \n",Poff,tmpF,tmpKoff,tmpK0,len); } } else { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; //printf("breaking: out of cut"); } // Checkpoint output: if (period_for_output > 0 ) if ((int)floor(sim_time/time_step) % period_for_output == 0 ) { FILE *fp; double tmpPon = 1.0 - exp( - ia_params->affinity_Kon*time_step); fp = fopen("affinity_check.dat","a"); fprintf(fp,"sim_time %f, period_for_output %d aff type: %d ",sim_time,period_for_output,aff_type_extracted); fprintf(fp,"Pon %f, Kon %f, particle %d, Poff = %f, F = %f, Koff = %f, K0 = %f, len = %f \n",tmpPon, ia_params->affinity_Kon, p1->p.identity, Poff,tmpF,tmpKoff,tmpK0,len); fclose(fp); } } else if (dist < ia_params->affinity_r0) { // Bond does not exist, we are inside of possible bond creation area, lets talk about creating a bond double Pon = 1.0 - exp( - ia_params->affinity_Kon*time_step); // The probability is given by function Pon(x)= 1 - e^(-x) where x is Kon*dt. Here is a table of values of this function, just to have an idea about the values // x | 0 | 0.25 | 0.5 | 0.75 | 1.0 | 1.5 | 2.0 | 3.0 | 5.0 // Pon(x) | 0 | 0.22 | 0.39 | 0.52 | 0.63 | 0.77 | 0.84 | 0.95 | 0.99 double decide = d_random(); if ( decide < Pon ) { // the bond will be created only with probability Pon. //printf("Creating: Pon = %f, decide = %f", Pon, decide); double folded_pos[3]; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); //printf("d: %f %f %f\n",d[0],d[1],d[2]); for(j=0;j<3;j++) p1->p.bond_site[j] = folded_pos[j] - d[j]; } else { //printf("In range, not creating: Pon = %f, decide = %f", Pon, decide); } } } } } if ( aff_type_extracted == 5 ) { //second implementation of affinity /************************ * * Here I can implement the affinity force. * I have the position of the particle - p1, and under p1->p.bond_site I have the coordinate of the bond_site. * Also, under d[3] I have the vector towards the constraint meaning that force on p1 should be in the direction of d[3]. * * Algorithm: * 1. First check is whether I am in the cut-off radius: ?dist < affinity_cut?. * 2. Then I check whether there exists a bond from the current particle: ?bond_site != -1? * 3. If yes, then I maintaind the bond. I put the forces and afterwards I decide whether the bond will brake or not. * 4. If no, I maintain the creation of a bond. First I check whether I am in the area of possible bond creation: ?dist < affinity_r0? * 5. If yes, I run the decision algorithm for bond creation and I either create or does not create the bond. * 6. If I am not in the area of possible bond creation I do nothing * * * comments: * strength of the force is proportiona to the difference of actual bond length and 75% of the relaxed bond length * bond is created with probability 1-exp(-Kon*timestep) * maxBond is not used, we use probability 1-exp(-Koff*timestep) to brake the bond * Koff depends on the bondlenth via Koff = K0*exp(F/Fd) = K0*exp(kappa(r-0.75*r0)/Fd) * here, ia_params->Koff gives us K_0, off rate when bond is relaxed. * here, maxBond is used as detachment force F_d. The original check for ensuring, that partice flows out of the cut-off radius and the bond remains active is replaced with fixed check, that bond length must not be greater that 0.8 cut_off *********************/ int j; double fac=0.0; if(CUTOFF_CHECK(dist < ia_params->affinity_cut)) { // Checking whether I am inside the interaction cut-off radius. if(dist > 0.0) { //printf("bond_site: %f %f %f\n",p1->p.bond_site[0],p1->p.bond_site[1],p1->p.bond_site[2]); if ((p1->p.bond_site[0] >= 0) && (p1->p.bond_site[1] >= 0) && (p1->p.bond_site[2] >= 0)) // Checking whether any bond exists { // Bond exists double folded_pos[3], vec[3], len2, len; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); for(j=0;j<3;j++) vec[j] = p1->p.bond_site[j] - folded_pos[j]; // Shouldn't be the vec vector normalized? Yes, but with affinity_r0 and not by len!!! len2 = sqrlen(vec); len = sqrt(len2); if (len > 0.75*(ia_params->affinity_r0)) { fac = ia_params->affinity_kappa*(len - 0.75*(ia_params->affinity_r0)); //printf("len %f r0 %f\n",len, ia_params->affinity_r0); } else fac = 0.0; //double ftemp = 0; for(j=0;j<3;j++) { force[j] += fac * vec[j] / len; // ftemp += abs(fac * vec[j] / len); } //if (ftemp > 0.000000000000001) printf("%f ",fac); // Decision whether I should break the bond: // First, force exerted on bond is stored in fac double tmpF = fac; // Then, zero force off rate K_0 is stored at ia_params_Koff double tmpK0 = ia_params->affinity_Koff; // Then, detachment force is stored in ia_params->affinity_maxBond double tmpFd = ia_params->affinity_maxBond; // Then, compute Koff double tmpKoff = tmpK0*exp( tmpF / tmpFd); // Finally, compute Poff double Poff = 1.0 - exp( - tmpKoff*time_step); //printf("%f ", Poff); if (len < 0.8*ia_params->affinity_cut) { // in other implementation, maxBond is used here. However, in this implementation, we need maxBond for setting detachment force F_d double decide = d_random(); if ( decide < Poff ) { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; // printf("bond broken. Poff = %f, F = %f, Koff = %f, K0 = %f, len = %f \n",Poff,tmpF,tmpKoff,tmpK0,len); } } else { for(j=0;j<3;j++) p1->p.bond_site[j] = -1; //printf("breaking: out of cut"); } // Checkpoint output: if (period_for_output > 0 ) if (((int)floor(sim_time/time_step) % period_for_output == 0 ) && (len > ia_params->affinity_r0) ) { FILE *fp; double tmpPon = 1.0 - exp( - ia_params->affinity_Kon*time_step); fp = fopen("affinity_check.dat","a"); fprintf(fp,"sim_time %f, period_for_output %d aff type: %d ",sim_time,period_for_output,aff_type_extracted); fprintf(fp,"Pon %f, Kon %f, particle %d, Poff = %f, F = %f, Koff = %f, K0 = %f, len = %f \n",tmpPon, ia_params->affinity_Kon, p1->p.identity, Poff,tmpF,tmpKoff,tmpK0,len); fclose(fp); } } else if (dist < ia_params->affinity_r0) { // Bond does not exist, we are inside of possible bond creation area, lets talk about creating a bond double Pon = 1.0 - exp( - ia_params->affinity_Kon*time_step); // The probability is given by function Pon(x)= 1 - e^(-x) where x is Kon*dt. Here is a table of values of this function, just to have an idea about the values // x | 0 | 0.25 | 0.5 | 0.75 | 1.0 | 1.5 | 2.0 | 3.0 | 5.0 // Pon(x) | 0 | 0.22 | 0.39 | 0.52 | 0.63 | 0.77 | 0.84 | 0.95 | 0.99 double decide = d_random(); if ( decide < Pon ) { // the bond will be created only with probability Pon. //printf("Creating: Pon = %f, decide = %f", Pon, decide); double folded_pos[3]; int img[3]; /* fold the coordinates of the particle */ memmove(folded_pos, p1->r.p, 3*sizeof(double)); memmove(img, p1->l.i, 3*sizeof(int)); unfold_position(folded_pos, img); //printf("folded positions: %f %f %f\n",folded_pos[0],folded_pos[1],folded_pos[2]); //printf("d: %f %f %f\n",d[0],d[1],d[2]); for(j=0;j<3;j++) p1->p.bond_site[j] = folded_pos[j] - d[j]; } else { //printf("In range, not creating: Pon = %f, decide = %f", Pon, decide); } } } } } }
int polymerC(int N_P, int MPC, double bond_length, int part_id, double *posed, int mode, double shield, int max_try, double val_cM, int cM_dist, int type_nM, int type_cM, int type_bond, double angle, double angle2, double *posed2, int constr) { int p,n, cnt1,cnt2,max_cnt, bond_size, *bond, i; double phi,zz,rr; double *poly; double pos[3]; double poz[3]; double poy[3] = {0, 0, 0}; double pox[3] = {0, 0, 0}; double a[3] = {0, 0, 0}; double b[3],c[3]={0., 0., 0.},d[3]; double absc; poly = (double*)malloc(3*MPC*sizeof(double)); bond_size = bonded_ia_params[type_bond].num; bond = (int*)malloc(sizeof(int) * (bond_size + 1)); bond[0] = type_bond; cnt1 = cnt2 = max_cnt = 0; for (p=0; p < N_P; p++) { for (cnt2=0; cnt2 < max_try; cnt2++) { /* place start monomer */ if (posed!=NULL) { /* if position of 1st monomer is given */ if (p > 0) { free(posed); posed=NULL; } else { pos[0]=posed[0]; pos[1]=posed[1]; pos[2]=posed[2]; } } else { /* randomly set position */ for (cnt1=0; cnt1<max_try; cnt1++) { pos[0]=box_l[0]*d_random(); pos[1]=box_l[1]*d_random(); pos[2]=box_l[2]*d_random(); if ((mode==1) || (collision(pos, shield, 0, NULL)==0)) break; POLY_TRACE(printf("s"); fflush(NULL)); } if (cnt1 >= max_try) { free(poly); return (-1); } } poly[0] = pos[0]; poly[1] = pos[1]; poly[2] = pos[2]; max_cnt=imax(cnt1, max_cnt); POLY_TRACE(printf("S"); fflush(NULL)); //POLY_TRACE(/* printf("placed Monomer 0 at (%f,%f,%f)\n",pos[0],pos[1],pos[2]) */); poz[0]=pos[0]; poz[1]=pos[1]; poz[2]=pos[2]; /* place 2nd monomer */ n=1; if (posed2 != NULL && posed != NULL && angle2 > -1.0) { /* if position of 2nd monomer is given */ pos[0]=posed2[0]; pos[1]=posed2[1]; pos[2]=posed2[2]; /* calculate preceding monomer so that bond_length is correct */ absc=sqrt(SQR(pos[0]-poz[0])+SQR(pos[1]-poz[1])+SQR(pos[2]-poz[2])); poz[0]=pos[0]+(poz[0]-pos[0])*bond_length/absc; poz[1]=pos[1]+(poz[1]-pos[1])*bond_length/absc; poz[2]=pos[2]+(poz[2]-pos[2])*bond_length/absc; //POLY_TRACE(/* printf("virtually shifted position of first monomer to (%f,%f,%f)\n",poz[0],poz[1],poz[2]) */); } else { /* randomly place 2nd monomer */ for (cnt1=0; cnt1<max_try; cnt1++) { zz = (2.0*d_random()-1.0)*bond_length; rr = sqrt(SQR(bond_length)-SQR(zz)); phi = 2.0*PI*d_random(); pos[0] = poz[0]+rr*cos(phi); pos[1] = poz[1]+rr*sin(phi); pos[2] = poz[2]+zz; #ifdef CONSTRAINTS if(constr==0 || constraint_collision(pos,poly+3*(n-1))==0){ #endif if (mode==1 || collision(pos, shield, n, poly)==0) break; if (mode==0) { cnt1 = -1; break; } #ifdef CONSTRAINTS } #endif POLY_TRACE(printf("m"); fflush(NULL)); } if (cnt1 >= max_try) { fprintf(stderr,"\nWarning! Attempt #%d to build polymer %d failed while placing monomer 2!\n",cnt2+1,p); fprintf(stderr," Retrying by re-setting the start-monomer of current chain...\n"); } if (cnt1 == -1 || cnt1 >= max_try) { continue; /* continue the main loop */ } } if(posed2!=NULL && p>0) { free(posed2); posed2=NULL; } poly[3*n] = pos[0]; poly[3*n+1] = pos[1]; poly[3*n+2] = pos[2]; max_cnt=imax(cnt1, max_cnt); POLY_TRACE(printf("M"); fflush(NULL)); //POLY_TRACE(/* printf("placed Monomer 1 at (%f,%f,%f)\n",pos[0],pos[1],pos[2]) */); /* place remaining monomers */ for (n=2; n<MPC; n++) { if (angle2 > -1.0) { if(n==2) { /* if the 2nd angle is set, construct preceding monomer with resulting plane perpendicular on the xy-plane */ poy[0]=2*poz[0]-pos[0]; poy[1]=2*poz[1]-pos[1]; if(pos[2]==poz[2]) poy[2]=poz[2]+1; else poy[2]=poz[2]; } else { /* save 3rd last monomer */ pox[0]=poy[0]; pox[1]=poy[1]; pox[2]=poy[2]; } } if (angle > -1.0) { /* save one but last monomer */ poy[0]=poz[0]; poy[1]=poz[1]; poy[2]=poz[2]; } /* save last monomer */ poz[0]=pos[0]; poz[1]=pos[1]; poz[2]=pos[2]; if(angle > -1.0){ a[0]=poy[0]-poz[0]; a[1]=poy[1]-poz[1]; a[2]=poy[2]-poz[2]; b[0]=pox[0]-poy[0]; b[1]=pox[1]-poy[1]; b[2]=pox[2]-poy[2]; vector_product(a,b,c); } for (cnt1=0; cnt1<max_try; cnt1++) { if(angle > -1.0) { if (sqrlen(c) < ROUND_ERROR_PREC) { fprintf(stderr, "WARNING: rotation axis is 0,0,0, check the angles given to the polymer command\n"); c[0] = 1; c[1] = 0; c[2] = 0; } if(angle2 > -1.0 && n>2) { vec_rotate(a,angle2,c,d); } else { phi = 2.0*PI*d_random(); vec_rotate(a,phi,c,d); } vec_rotate(d,angle,a,b); pos[0] = poz[0] + b[0]; pos[1] = poz[1] + b[1]; pos[2] = poz[2] + b[2]; } else { zz = (2.0*d_random()-1.0)*bond_length; rr = sqrt(SQR(bond_length)-SQR(zz)); phi = 2.0*PI*d_random(); pos[0] = poz[0]+rr*cos(phi); pos[1] = poz[1]+rr*sin(phi); pos[2] = poz[2]+zz; } //POLY_TRACE(/* printf("a=(%f,%f,%f) absa=%f M=(%f,%f,%f) c=(%f,%f,%f) absMc=%f a*c=%f)\n",a[0],a[1],a[2],sqrt(SQR(a[0])+SQR(a[1])+SQR(a[2])),M[0],M[1],M[2],c[0],c[1],c[2],sqrt(SQR(M[0]+c[0])+SQR(M[1]+c[1])+SQR(M[2]+c[2])),a[0]*c[0]+a[1]*c[1]+a[2]*c[2]) */); //POLY_TRACE(/* printf("placed Monomer %d at (%f,%f,%f)\n",n,pos[0],pos[1],pos[2]) */); #ifdef CONSTRAINTS if(constr==0 || constraint_collision(pos,poly+3*(n-1))==0){ #endif if (mode==1 || collision(pos, shield, n, poly)==0) break; if (mode==0) { cnt1 = -2; break; } #ifdef CONSTRAINTS } #endif POLY_TRACE(printf("m"); fflush(NULL)); } if (cnt1 >= max_try) { fprintf(stderr,"\nWarning! Attempt #%d to build polymer %d failed after %d unsuccessful trials to place monomer %d!\n",cnt2+1,p,cnt1,n); fprintf(stderr," Retrying by re-setting the start-monomer of current chain...\n"); } if (cnt1 == -2 || cnt1 >= max_try) { n=0; break; } poly[3*n] = pos[0]; poly[3*n+1] = pos[1]; poly[3*n+2] = pos[2]; max_cnt=imax(cnt1, max_cnt); POLY_TRACE(printf("M"); fflush(NULL)); } if (n>0) break; } /* cnt2 */ POLY_TRACE(printf(" %d/%d->%d \n",cnt1,cnt2,max_cnt)); if (cnt2 >= max_try) { free(poly); return(-2); } else max_cnt = imax(max_cnt,imax(cnt1,cnt2)); /* actually creating current polymer in ESPResSo */ for (n=0; n<MPC; n++) { pos[0] = poly[3*n]; pos[1] = poly[3*n+1]; pos[2] = poly[3*n+2]; if (place_particle(part_id, pos)==ES_PART_ERROR || (set_particle_q(part_id, ((n % cM_dist==0) ? val_cM : 0.0) )==ES_ERROR) || (set_particle_type(part_id, ((n % cM_dist==0) ? type_cM : type_nM) )==ES_ERROR)) { free(poly); return (-3); } if(n>=bond_size){ bond[1] = part_id - bond_size; for(i=2;i<=bond_size;i++){ bond[i] = part_id - bond_size + i; } if(change_particle_bond(part_id-bond_size+1, bond, 0)==ES_ERROR) { free(poly); return (-3); } } part_id++; //POLY_TRACE(/* printf("placed Monomer %d at (%f,%f,%f)\n",n,pos[0],pos[1],pos[2]) */); } } free(poly); return(imax(max_cnt,cnt2)); }