예제 #1
0
/* 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());
}
예제 #2
0
/** 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;
}
예제 #3
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;
}
예제 #4
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) );
}
예제 #5
0
/** 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;

  }

}
예제 #6
0
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) );
}
예제 #7
0
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));
}
예제 #8
0
/** 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;
}
예제 #9
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); 
}
예제 #10
0
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;
      }
  }
}
예제 #12
0
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();
  }
}
예제 #13
0
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));
}
예제 #14
0
/** 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;

  }

}
예제 #15
0
파일: dpd.hpp 프로젝트: tojb/espresso
/** 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
}
예제 #16
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];
  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);
  }
예제 #17
0
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

}
예제 #18
0
/** 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);
				}
			}
		}
	  }
  }  

}
예제 #19
0
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));
}