Esempio n. 1
0
void integrate_vv(int n_steps)
{
  int i;

  /* 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

   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;
  }

  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 ROTATION
    propagate_omega_quat();
#endif

#ifdef BOND_CONSTRAINT
    /**Correct those particle positions that participate in a rigid/constrained bond */
    ghost_communicator(&cell_structure.update_ghost_pos_comm);
    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

    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 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, MPI_COMM_WORLD);
    MPI_Bcast(&nptiso.p_diff, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    MPI_Bcast(&nptiso.volume, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    if(this_node==0) nptiso.p_inst_av /= 1.0*n_steps;
    MPI_Bcast(&nptiso.p_inst_av, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  }
#endif

}
Esempio n. 2
0
void integrate_vv(int n_steps)
{
  int i;

  /* 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

   
   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;

  }

  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 ROTATION
    propagate_omega_quat();
#endif

#ifdef BOND_CONSTRAINT
    /**Correct those particle positions that participate in a rigid/constrained bond */
    ghost_communicator(&cell_structure.update_ghost_pos_comm);
    correct_pos_shake();
#endif

#ifdef ELECTROSTATICS
    if(coulomb.method == COULOMB_MAGGS) {
      propagate_B_field(0.5*time_step); 
      if(maggs.yukawa)
	maggs_propagate_psi_vel_pos(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;
#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

    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();

#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

//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) {
      propagate_B_field(0.5*time_step); 
      if(maggs.yukawa)
	maggs_propagate_psi_vel(0.5*time_step);
      MAGGS_TRACE(check_gauss_law();); 
    }
int lattice_read_file(Lattice* lattice, char* filename) {
 // ExternalPotentialTabulated *e = &(external_potentials[number].e.tabulated);
  FILE* infile = fopen(filename, "r");
  
  if (!infile)  {
    runtimeErrorMsg() <<"Could not open file "<< filename << "\n";
    return ES_ERROR;
  }
  char first_line[100];
  char* token;
  double res[3];
  double size[3];
  double offset[3]={0,0,0};
  int dim=0;
  if (fgets(first_line, 100, infile) == NULL) {
      fprintf(stderr, "Nothing read from file\n");
      return ES_ERROR;
  }

  token = strtok(first_line, " \t");
  if (!token) { fprintf(stderr, "Error reading dimensionality\n"); return ES_ERROR; }
  dim = atoi(token);
  if (dim<=0)  { fprintf(stderr, "Error reading dimensionality\n"); return ES_ERROR; }
  
  token = strtok(NULL, " \t");
  if (!token) { fprintf(stderr, "Could not read box_l[0]\n"); return ES_ERROR; }
  size[0] = atof(token);

  token = strtok(NULL, " \t");
  if (!token) { fprintf(stderr, "Could not read box_l[1]\n"); return ES_ERROR; }
  size[1] = atof(token);
  
  token = strtok(NULL, " \t");
  if (!token) { fprintf(stderr, "Could not read box_l[2]\n"); return ES_ERROR;}
  size[2] = atof(token);

  token = strtok(NULL, " \t");
  if (!token) { fprintf(stderr, "Could not read res[0]\n"); return ES_ERROR;}
  res[0] = atof(token);
  
  token = strtok(NULL, " \t");
  if (!token) { fprintf(stderr, "Could not read res[1]\n"); return ES_ERROR;}
  res[1] = atof(token);
  
  token = strtok(NULL, " \t");
  if (!token) { fprintf(stderr, "Could not read res[2]\n"); return ES_ERROR;}
  res[2] = atof(token);

  token = strtok(NULL, " \t");
  if (token) {
    offset[0]=atof(token);
    token = strtok(NULL, " \t");
    if (!token) { fprintf(stderr, "Could not read offset[1]\n"); return ES_ERROR;}
    offset[1] = atof(token);
    token = strtok(NULL, " \t");
    if (!token) { fprintf(stderr, "Could not read offset[2]\n"); return ES_ERROR;}
    offset[2] = atof(token);
  }
  lattice->offset[0]=offset[0];
  lattice->offset[1]=offset[1];
  lattice->offset[2]=offset[2];

  int halosize=1;

  if (size[0] > 0 && fabs(size[0] - box_l[0]) > ROUND_ERROR_PREC) {
    runtimeErrorMsg() <<"Box size in x is wrong "<< size[0] << " vs " << box_l[0] <<"\n";
    return ES_ERROR;
  }
  if (size[1] > 0 && fabs(size[1] - box_l[1]) > ROUND_ERROR_PREC) {
    runtimeErrorMsg() <<"Box size in y is wrong "<< size[1] << " vs " << box_l[1] <<"\n";
    return ES_ERROR;
  }
  if (size[2] > 0 && fabs(size[2] - box_l[2]) > ROUND_ERROR_PREC) {
    runtimeErrorMsg() <<"Box size in z is wrong "<< size[2] << " vs " << box_l[2] <<"\n";
    return ES_ERROR;
  }


  if (res[0] > 0)
    if (skin/res[0]>halosize) halosize = (int)ceil(skin/res[0]);
  if (res[1] > 0)
    if (skin/res[1]>halosize) halosize = (int)ceil(skin/res[1]);
  if (res[2] > 0)
    if (skin/res[2]>halosize) halosize = (int)ceil(skin/res[2]);

  // Now we count how many entries we have:

  lattice->init(res, offset, halosize, dim);
  lattice->interpolation_type = INTERPOLATION_LINEAR;

  char* line = (char*) Utils::malloc((3+dim)*ES_DOUBLE_SPACE);
  double pos[3];
  double f[3];
  int i;
  
  while (fgets(line, 200, infile)) {
    if (strlen(line)<2)
      continue;
    token = strtok(line, " \t");
    if (!token) { fprintf(stderr, "Could not read pos[0]\n"); return ES_ERROR; }
    pos[0] = atof(token);

    token = strtok(NULL, " \t");
    if (!token) { fprintf(stderr, "Could not read pos[1] in line:\n%s\n", line); return ES_ERROR; }
    pos[1] = atof(token);
    
    token = strtok(NULL, " \t");
    if (!token) { fprintf(stderr, "Could not read pos[1]\n"); return ES_ERROR; }
    pos[2] = atof(token);
    for (i=0; i<dim;i++) {
      token = strtok(NULL, " \t");
      if (!token) { fprintf(stderr, "Could not read f[%d]\n", i); return ES_ERROR; }
      f[i] = atof(token);
    }
    lattice->set_data_for_global_position_with_periodic_image(pos, f);
  }
  free(line);

  write_local_lattice_to_file("lattice", lattice);
  
  if (check_runtime_errors()!=0)
    return ES_ERROR;
  return ES_OK;
}
Esempio n. 4
0
void on_integration_start()
{
  char *errtext;

  EVENT_TRACE(fprintf(stderr, "%d: on_integration_start\n", this_node));
  INTEG_TRACE(fprintf(stderr,"%d: on_integration_start: reinit_thermo = %d, resort_particles=%d\n",
		      this_node,reinit_thermo,resort_particles));

  /********************************************/
  /* sanity checks                            */
  /********************************************/

  if ( time_step < 0.0 ) {
    errtext = runtime_error(128);
    ERROR_SPRINTF(errtext, "{010 time_step not set} ");
  }
  if ( skin < 0.0 ) {
    errtext = runtime_error(128);
    ERROR_SPRINTF(errtext,"{011 skin not set} ");
  }
  if ( temperature < 0.0 ) {
    errtext = runtime_error(128);
    ERROR_SPRINTF(errtext,"{012 thermostat not initialized} ");
  }
  
#ifdef NPT
  if (integ_switch == INTEG_METHOD_NPT_ISO) {
    if (nptiso.piston <= 0.0) {
      char *errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{014 npt on, but piston mass not set} ");
    }
  
#ifdef ELECTROSTATICS

    switch(coulomb.method) {
    case COULOMB_NONE:  break;
#ifdef P3M
    case COULOMB_P3M:   break;
#endif /*P3M*/
    default: {
      char *errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{014 npt only works with P3M} ");
    }
    }
#endif /*ELECTROSTATICS*/

#ifdef DIPOLES

    switch (coulomb.Dmethod) {
    case DIPOLAR_NONE: break;
#ifdef DP3M
    case DIPOLAR_P3M: break;
#endif
    default: {
      char *errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"NpT does not work with your dipolar method, please use P3M.");
    }
    }
#endif  /* ifdef DIPOLES */
  }
#endif /*NPT*/

  if (!check_obs_calc_initialized()) return;

#ifdef LB
  if(lattice_switch & LATTICE_LB) {
    if (lbpar.agrid <= 0.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{098 Lattice Boltzmann agrid not set} ");
    }
    if (lbpar.tau <= 0.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{099 Lattice Boltzmann time step not set} ");
    }
    if (lbpar.rho <= 0.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{100 Lattice Boltzmann fluid density not set} ");
    }
    if (lbpar.viscosity <= 0.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{101 Lattice Boltzmann fluid viscosity not set} ");
    }
    if (dd.use_vList && skin>=lbpar.agrid/2.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext, "{104 LB requires either no Verlet lists or that the skin of the verlet list to be less than half of lattice-Boltzmann grid spacing.} ");
    }
  }
#endif
#ifdef LB_GPU
if(this_node == 0){
  if(lattice_switch & LATTICE_LB_GPU) {
    if (lbpar_gpu.agrid < 0.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{098 Lattice Boltzmann agrid not set} ");
    }
    if (lbpar_gpu.tau < 0.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{099 Lattice Boltzmann time step not set} ");
    }
    if (lbpar_gpu.rho < 0.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{100 Lattice Boltzmann fluid density not set} ");
    }
    if (lbpar_gpu.viscosity < 0.0) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{101 Lattice Boltzmann fluid viscosity not set} ");
    }
    if (lb_reinit_particles_gpu) {
	lb_realloc_particles_gpu();
	lb_reinit_particles_gpu = 0;
    }
  }
}

#endif

#ifdef METADYNAMICS
  meta_init();
#endif

#ifdef CATALYTIC_REACTIONS
if(reaction.ct_rate != 0.0) {

   if( dd.use_vList == 0 || cell_structure.type != CELL_STRUCTURE_DOMDEC) {
      errtext = runtime_error(128);
      ERROR_SPRINTF(errtext,"{105 The CATALYTIC_REACTIONS feature requires verlet lists and domain decomposition} ");
      check_runtime_errors();
    }

  if(max_cut < reaction.range) {
    errtext = runtime_error(128);
    ERROR_SPRINTF(errtext,"{106 Reaction range of %f exceeds maximum cutoff of %f} ", reaction.range, max_cut);
  }
}
#endif

  /********************************************/
  /* end sanity checks                        */
  /********************************************/


  /* Prepare the thermostat */
  if (reinit_thermo) {
    thermo_init();
    reinit_thermo = 0;
    recalc_forces = 1;
  }

  /* Ensemble preparation: NVT or NPT */
  integrate_ensemble_init();

  /* Update particle and observable information for routines in statistics.c */
  invalidate_obs();
  freePartCfg();

  on_observable_calc();
}
Esempio n. 5
0
void integrate_sd(int n_steps)
{
  /* Prepare the Integrator */
  on_integration_start();

  /* if any method vetoes (P3M not initialized), immediately bail out */
  if (check_runtime_errors())
    return;

  INTEG_TRACE(fprintf(stderr,"%d: integrate_vv: integrating %d steps (recalc_forces=%d)\n",
		      this_node, n_steps, recalc_forces));
   
  /* Integration Step:
     Calculate forces f(t) as function of positions p(t) ( and velocities v(t) ) */
  //if (recalc_forces) { 
  //thermo_heat_up();


  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
  // prob. works only with harmonic bounds
  calc_and_apply_mol_constraints();
#endif

  /* should be pretty late, since it needs to zero out the total force */
#ifdef COMFIXED
  calc_comfixed();
#endif

  //rescale_forces();
    
#ifdef COLLISION_DETECTION
  //should not be neccessery, as integrator avoids collision
  handle_collisions();
#endif
  // end of force calculation

#ifdef GHMC
  if(thermo_switch & THERMO_GHMC)
    ghmc_init();
#endif
  
  if (check_runtime_errors())
    return;

  n_verlet_updates = 0;

  /* Integration loop */
  for(int step=0;step<n_steps;step++) {
    INTEG_TRACE(fprintf(stderr,"%d: STEP %d\n",this_node,step));
    //sd_set_particles_apart();
#ifdef BOND_CONSTRAINT
    save_old_pos();
#endif

#ifdef GHMC
    if(thermo_switch & THERMO_GHMC) {
      if (step % ghmc_nmd == 0)
        ghmc_momentum_update();
    }
#endif
    if(thermo_switch & ~(THERMO_SD|THERMO_BD) ){
      static bool warned_thermo_sd_other=false;
      if (!warned_thermo_sd_other){
	fprintf (stderr, "Warning, using another thermo than the one provided by StokesDynamics breaks (most likely) StokesDynamics.\n");
	warned_thermo_sd_other=true;
      }
    }
    if (thermo_switch & THERMO_SD && thermo_switch &THERMO_BD) {
      fprintf (stderr, "Warning: cannot use BD and SD. Disabeling BD!\n");
      thermo_switch &= ~THERMO_BD;
    }

    /* Integration Step: Step 3 of Velocity Verlet scheme:
       Calculate f(t) as function of positions p(t) ( and ``velocities'' v(t) ) */

#ifdef LB
    transfer_momentum = 1;
#endif
#ifdef LB_GPU
    transfer_momentum_gpu = 1;
#endif

    force_calc();

#ifdef CATALYTIC_REACTIONS
    integrate_reaction();
#endif

    if (check_runtime_errors())
      break;

    
#ifdef LB
    if (lattice_switch & LATTICE_LB)
      lattice_boltzmann_update();
      
    if (check_runtime_errors())
      break;
#endif

#ifdef LB_GPU
    if(this_node == 0){
#ifdef ELECTROKINETICS
      if (ek_initialized) {
        ek_integrate();
      }
      else {
#endif
        if (lattice_switch & LATTICE_LB_GPU)
          lattice_boltzmann_update_gpu();
#ifdef ELECTROKINETICS
      }
#endif
    }
#endif //LB_GPU

#ifdef ELECTROSTATICS
    if(coulomb.method == COULOMB_MAGGS) {
      maggs_propagate_B_field(0.5*time_step); 
    }
#endif

#ifdef NPT
    if((this_node==0) && (integ_switch == INTEG_METHOD_NPT_ISO))
      nptiso.p_inst_av += nptiso.p_inst;
#endif

#ifdef GHMC
    if(thermo_switch & THERMO_GHMC) {
      if (step % ghmc_nmd == ghmc_nmd-1)
        ghmc_mc();
    }
#endif



    /** Integration Steps: Update the Positions
      \[ p_i(t + dt)   = p_i(t) + dt * \mu_{ij} * f_j(t) + dt * \mu_{ij} * f^B_j \]
    */
    propagate_pos_sd(); // we dont have velocities

#ifdef BOND_CONSTRAINT
    static bool bond_constraint_with_sd_warned=false;
    if (!bond_constraint_with_sd_warned){ // warn only once
      fprintf (stderr, "Warning, using BOND_CONSTRAINT with StokesDynamics might not work as expected!.\n");    
      bond_constraint_with_sd_warned=true;
    }
    /**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


    /* 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

#ifdef GHMC
  if(thermo_switch & THERMO_GHMC)
    ghmc_close();
#endif

}
Esempio n. 6
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

}
Esempio n. 7
0
void integrate_vv(int n_steps, int reuse_forces)
{
  /* Prepare the Integrator */
  on_integration_start();
 
  #ifdef IMMERSED_BOUNDARY
    // Here we initialize volume conservation
    // This function checks if the reference volumes have been set and if necessary calculates them
    IBM_InitVolumeConservation();
  #endif

  /* 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) ) */
  /* reuse_forces logic:
     -1: recalculate forces unconditionally, mostly used for timing
      0: recalculate forces if recalc_forces is set, meaning it is probably necessary
      1: do not recalculate forces. Mostly when reading checkpoints with forces
   */
  if (reuse_forces == -1 || (recalc_forces && reuse_forces != 1)) {
    thermo_heat_up();

#ifdef LB
    transfer_momentum = 0;
    if (lattice_switch & LATTICE_LB && this_node == 0)
      if (warnings) fprintf (stderr, "Warning: Recalculating forces, so the LB coupling forces are not included in the particle force the first time step. This only matters if it happens frequently during sampling.\n");
#endif
#ifdef LB_GPU
    transfer_momentum_gpu = 0;
    if (lattice_switch & LATTICE_LB_GPU && this_node == 0)
      if (warnings) fprintf (stderr, "Warning: Recalculating forces, so the LB coupling forces are not included in the particle force the first time step. This only matters if it happens frequently during sampling.\n");
#endif

    force_calc();

    if(integ_switch != INTEG_METHOD_STEEPEST_DESCENT) {
      rescale_forces();
#ifdef ROTATION
      convert_initial_torques();
#endif
    }

    thermo_cool_down();
  }

#ifdef GHMC
  if(thermo_switch & THERMO_GHMC)
    ghmc_init();
#endif

  if (check_runtime_errors())
    return;

  n_verlet_updates = 0;

  /* Integration loop */
  for (int step=0; step<n_steps; step++) {
    INTEG_TRACE(fprintf(stderr,"%d: STEP %d\n", this_node, step));

#ifdef BOND_CONSTRAINT
    save_old_pos();
#endif

#ifdef GHMC
    if(thermo_switch & THERMO_GHMC) {
      if (step % ghmc_nmd == 0)
        ghmc_momentum_update();
    }
#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 if(integ_switch == INTEG_METHOD_STEEPEST_DESCENT) {
      if(steepest_descent_step())
	break;
    } 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

    /* 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

    force_calc();
    
// IMMERSED_BOUNDARY
#ifdef IMMERSED_BOUNDARY
    // Now the forces are computed and need to go into the LB fluid
    if (lattice_switch & LATTICE_LB) IBM_ForcesIntoFluid_CPU();
#ifdef LB_GPU
    if (lattice_switch & LATTICE_LB_GPU) IBM_ForcesIntoFluid_GPU();
#endif
#endif

#ifdef CATALYTIC_REACTIONS
    integrate_reaction();
#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) */
    if(integ_switch != INTEG_METHOD_STEEPEST_DESCENT) {
      rescale_forces_propagate_vel();
#ifdef ROTATION
    convert_torques_propagate_omega();
#endif
    }
    // SHAKE velocity updates
#ifdef BOND_CONSTRAINT
    ghost_communicator(&cell_structure.update_ghost_pos_comm);
    correct_vel_shake();
#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

    // progagate one-step functionalities
#ifdef LB
    if (lattice_switch & LATTICE_LB)
      lattice_boltzmann_update();
      
    if (check_runtime_errors())
      break;
#endif

#ifdef LB_GPU
    if(this_node == 0){
#ifdef ELECTROKINETICS
      if (ek_initialized) {
        ek_integrate();
      }
      else {
#endif
        if (lattice_switch & LATTICE_LB_GPU)
          lattice_boltzmann_update_gpu();
#ifdef ELECTROKINETICS
      }
#endif
    }
#endif //LB_GPU
    
// IMMERSED_BOUNDARY
#ifdef IMMERSED_BOUNDARY
    
    IBM_UpdateParticlePositions();
    // We reset all since otherwise the halo nodes may not be reset
    // NB: the normal Espresso reset is also done after applying the forces
//    if (lattice_switch & LATTICE_LB) IBM_ResetLBForces_CPU();
#ifdef LB_GPU
    //if (lattice_switch & LATTICE_LB_GPU) IBM_ResetLBForces_GPU();
#endif
    
    if (check_runtime_errors()) break;
    
    // Ghost positions are now out-of-date
    // We should update.
    // Actually we seem to get the same results whether we do this here or not, but it is safer to do it
    ghost_communicator(&cell_structure.update_ghost_pos_comm);
    
#endif // IMMERSED_BOUNDARY

#ifdef ELECTROSTATICS
    if(coulomb.method == COULOMB_MAGGS) {
      maggs_propagate_B_field(0.5*time_step); 
    }
#endif

#ifdef NPT
    if((this_node==0) && (integ_switch == INTEG_METHOD_NPT_ISO))
      nptiso.p_inst_av += nptiso.p_inst;
#endif

#ifdef GHMC
    if(thermo_switch & THERMO_GHMC) {
      if (step % ghmc_nmd == ghmc_nmd-1)
        ghmc_mc();
    }
#endif

    if(integ_switch != INTEG_METHOD_STEEPEST_DESCENT) {
      /* 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

#ifdef GHMC
  if(thermo_switch & THERMO_GHMC)
    ghmc_close();
#endif

}
Esempio n. 8
0
void integrate_vv(int n_steps, int reuse_forces)
{
  int i;

  /* 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) ) */
  /* reuse_forces logic:
     -1: recalculate forces unconditionally, mostly used for timing
      0: recalculate forces if recalc_forces is set, meaning it is probably necessary
      1: do not recalculate forces. Mostly when reading checkpoints with forces
   */
  if (reuse_forces == -1 || (recalc_forces && reuse_forces != 1)) {
    thermo_heat_up();

#ifdef LB
    transfer_momentum = 0;
    if (lattice_switch & LATTICE_LB && this_node == 0)
      if (warnings) fprintf (stderr, "Warning: Recalculating forces, so the LB coupling forces are not included in the particle force the first time step. This only matters if it happens frequently during sampling.\n");
#endif
#ifdef LB_GPU
    transfer_momentum_gpu = 0;
    if (lattice_switch & LATTICE_LB_GPU && this_node == 0)
      if (warnings) fprintf (stderr, "Warning: Recalculating forces, so the LB coupling forces are not included in the particle force the first time step. This only matters if it happens frequently during sampling.\n");
#endif

    force_calc();

    rescale_forces();
#ifdef ROTATION
    convert_initial_torques();
#endif
    
    thermo_cool_down();
  }

#ifdef GHMC
  if(thermo_switch & THERMO_GHMC)
    ghmc_init();
#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

#ifdef GHMC
    if(thermo_switch & THERMO_GHMC) {
      if ((int) fmod(i,ghmc_nmd) == 0)
        ghmc_momentum_update();
    }
#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

    /* 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

    force_calc();

#ifdef CATALYTIC_REACTIONS
    integrate_reaction();
#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();
#ifdef ROTATION
    convert_torques_propagate_omega();
#endif
    // SHAKE velocity updates
#ifdef BOND_CONSTRAINT
    ghost_communicator(&cell_structure.update_ghost_pos_comm);
    correct_vel_shake();
#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

    // progagate one-step functionalities
#ifdef LB
    if (lattice_switch & LATTICE_LB)
      lattice_boltzmann_update();
      
    if (check_runtime_errors())
      break;
#endif

#ifdef LB_GPU
    if(this_node == 0){
#ifdef ELECTROKINETICS
      if (ek_initialized) {
        ek_integrate();
      }
      else {
#endif
        if (lattice_switch & LATTICE_LB_GPU)
          lattice_boltzmann_update_gpu();
#ifdef ELECTROKINETICS
      }
#endif
    }
#endif //LB_GPU

#ifdef ELECTROSTATICS
    if(coulomb.method == COULOMB_MAGGS) {
      maggs_propagate_B_field(0.5*time_step); 
    }
#endif

#ifdef NPT
    if((this_node==0) && (integ_switch == INTEG_METHOD_NPT_ISO))
      nptiso.p_inst_av += nptiso.p_inst;
#endif

#ifdef GHMC
    if(thermo_switch & THERMO_GHMC) {
      if ((int) fmod(i,ghmc_nmd) == ghmc_nmd-1)
        ghmc_mc();
    }
#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

#ifdef GHMC
  if(thermo_switch & THERMO_GHMC)
    ghmc_close();
#endif

}