int mmm1d_tune(char **log)
{
  char buffer[32 + 2*ES_DOUBLE_SPACE + ES_INTEGER_SPACE];
  double int_time, min_time=1e200, min_rad = -1;
  double maxrad = box_l[2]; /* N_psi = 2, theta=2/3 maximum for rho */
  double switch_radius;

  if (mmm1d_params.far_switch_radius_2 < 0) {
    /* determine besselcutoff and optimal switching radius. Should be around 0.33 */
    for (switch_radius = 0.2*maxrad;
	 switch_radius < 0.4*maxrad;
	 switch_radius += 0.025*maxrad) {
      if (switch_radius <= bessel_radii[MAXIMAL_B_CUT - 1]) {
        // this switching radius is too small for our Bessel series
        continue;
      }

      mmm1d_params.far_switch_radius_2 = SQR(switch_radius);

      coulomb.method = COULOMB_MMM1D;
      
      /* initialize mmm1d temporary structures */
      mpi_bcast_coulomb_params();

      /* perform force calculation test */
      int_time = time_force_calc(TEST_INTEGRATIONS);

      /* exit on errors */
      if (int_time < 0)
	return ES_ERROR;

      sprintf(buffer, "r= %f t= %f ms\n", switch_radius, int_time);
      *log = strcat_alloc(*log, buffer);

      if (int_time < min_time) {
	min_time = int_time;
	min_rad = switch_radius;
      }
      /* stop if all hope is vain... */
      else if (int_time > 2*min_time)
	break;
    }
    switch_radius = min_rad;
    mmm1d_params.far_switch_radius_2 = SQR(switch_radius);
  }
  else {
    if (mmm1d_params.far_switch_radius_2 <= SQR(bessel_radii[MAXIMAL_B_CUT - 1])) {
      // this switching radius is too small for our Bessel series
      *log = strcat_alloc(*log, "could not find reasonable bessel cutoff");
      return ES_ERROR;
    }
  }

  coulomb.method = COULOMB_MMM1D;

  mpi_bcast_coulomb_params();

  return ES_OK;
}
Ejemplo n.º 2
0
/** Determine runtime for a specific cutoff */
double time_r_cut(double r_cut) {
  double t;

  /** Set cutoff to time */
  scafacos->set_r_cut(r_cut);

  /** Tune other parameters */
  scafacos->tune(particles.charges, particles.positions);
  
  on_coulomb_change();
  
  return time_force_calc(10);
}
Ejemplo n.º 3
0
int tclcommand_time_integration(ClientData data, Tcl_Interp *interp, int argc, char *argv[]) {
  char buffer[10+TCL_DOUBLE_SPACE];
  double t;
  int n = 1;
  if(argc > 2) {
    Tcl_AppendResult(interp, "time_integration expects zero or one argument.", (char *)NULL);
    return TCL_ERROR;
  }
  if(argc == 2) {
    if(!(ARG1_IS_I(n) && (n > 1))) {
      return TCL_ERROR;
    }
  }

  t = time_force_calc(n);

  sprintf(buffer, "%lf", t);
  Tcl_AppendResult(interp, buffer, (char *)NULL);
  return TCL_OK;
}
Ejemplo n.º 4
0
//Tuning
int EwaldgpuForce::adaptive_tune(char **log,SystemInterface &s)
{
	ewaldgpu_params.isTuned = false;
	int Kmax = ewaldgpu_params.K_max;
	double alpha_array[Kmax]; //All computed alpha in dependence of K
	double rcut_array[Kmax]; //All computed r_cut in dependence of all computed alpha

	//Squared charge
	Particle *particle;
	particle = (Particle*)malloc(n_part*sizeof(Particle));
	mpi_get_particles(particle, NULL);
	double q_sqr = compute_q_sqare(particle);

	char b[3*ES_INTEGER_SPACE + 3*ES_DOUBLE_SPACE + 128];

  if (skin == -1) {
    *log = strcat_alloc(*log, "ewaldgpu cannot be tuned, since the skin is not yet set");
    return ES_ERROR;
  }

	//Compute alpha for all reciprocal k-sphere radius K
	for(int K = 0; K < Kmax ;K++)
	{
		alpha_array[K] = tune_alpha(ewaldgpu_params.accuracy/sqrt(2), ewaldgpu_params.precision, K+1, box_l[0]*box_l[1]*box_l[2], q_sqr, n_part);
		//printf("K:%i alpha:%f\n",K+1,alpha_array[K]);
	}
	//Compute r_cut for all computed alpha
	for(int K = 0; K < Kmax ;K++)
	{
		rcut_array[K] = tune_rcut(ewaldgpu_params.accuracy/sqrt(2), ewaldgpu_params.precision, alpha_array[K], box_l[0]*box_l[1]*box_l[2], q_sqr, n_part);
		//printf("K:%i rcut:%f \n",K+1,rcut_array[K]);
	}
	//Test if accuracy was reached
	if(rcut_array[Kmax-1]<0)
  {
    return ES_ERROR;
  }

	/***********************************************************************************
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	PERFORMANCE TIME
	 ***********************************************************************************/

	//Test performance time for the diverent (K, rcut, alpha)
	double int_time_best = 1E30;
	int K_best = Kmax;
	for(int K = 0; K < Kmax ;K++)
	{
		if(alpha_array[K]>0 and rcut_array[K]>0 and rcut_array[K]<(std::min(box_l[0],std::min(box_l[1],box_l[2])))/2.0-skin)
		{
			set_params(rcut_array[K], K+1, K+1, K+1, alpha_array[K]);
			mpi_bcast_coulomb_params();
			double int_time = time_force_calc(ewaldgpu_params.time_calc_steps);
			if(int_time<int_time_best)
			{
				int_time_best = int_time;
				K_best = K;
			}
			//printf("TIME K:%i int_time:%f\n",K+1,int_time);
		}
	}

	set_params(rcut_array[K_best], K_best+1, K_best+1, K_best+1, alpha_array[K_best]);
  ewaldgpu_params.isTuned = true;
	mpi_bcast_coulomb_params();

  //Print Status
  sprintf(b, "ewaldgpu tune parameters: Accuracy goal = %f\n", ewaldgpu_params.accuracy);
  *log = strcat_alloc(*log, b);
  sprintf(b, "ewaldgpu tune parameters: Alpha = %f\n", ewaldgpu_params.alpha);
  *log = strcat_alloc(*log, b);
  sprintf(b, "ewaldgpu tune parameters: r_cut = %f\n", ewaldgpu_params.rcut);
  *log = strcat_alloc(*log, b);
  sprintf(b, "ewaldgpu tune parameters: num_kx = %i\n", ewaldgpu_params.num_kx);
  *log = strcat_alloc(*log, b);
  sprintf(b, "ewaldgpu tune parameters: num_ky = %i\n", ewaldgpu_params.num_ky);
  *log = strcat_alloc(*log, b);
  sprintf(b, "ewaldgpu tune parameters: num_kz = %i\n", ewaldgpu_params.num_kz);
  *log = strcat_alloc(*log, b);

  return ES_OK;
}
Ejemplo n.º 5
0
int mmm1d_tune(char **log)
{
  char buffer[32 + 2*ES_DOUBLE_SPACE + ES_INTEGER_SPACE];
  double int_time, min_time=1e200, min_rad = -1;
  double maxrad = box_l[2]; /* N_psi = 2, theta=2/3 maximum for rho */
  double switch_radius;

  if (mmm1d_params.bessel_cutoff < 0 && mmm1d_params.far_switch_radius_2 < 0) {
    /* determine besselcutoff and optimal switching radius */
    for (switch_radius = RAD_STEPPING*maxrad;
	 switch_radius < maxrad;
	 switch_radius += RAD_STEPPING*maxrad) {
      mmm1d_params.bessel_cutoff = determine_bessel_cutoff(switch_radius, mmm1d_params.maxPWerror, MAXIMAL_B_CUT);
      /* no reasonable cutoff possible */
      if (mmm1d_params.bessel_cutoff == MAXIMAL_B_CUT)
	continue;
      mmm1d_params.far_switch_radius_2 = SQR(switch_radius);

      coulomb.method = COULOMB_MMM1D;
      
      /* initialize mmm1d temporary structures */
      mpi_bcast_coulomb_params();

      /* perform force calculation test */
      int_time = time_force_calc(TEST_INTEGRATIONS);

      /* exit on errors */
      if (int_time < 0)
	return ES_ERROR;

      sprintf(buffer, "r= %f c= %d t= %f ms\n",
	      switch_radius, mmm1d_params.bessel_cutoff, int_time);
      *log = strcat_alloc(*log, buffer);

      if (int_time < min_time) {
	min_time = int_time;
	min_rad = switch_radius;
      }
      /* stop if all hope is vain... */
      else if (int_time > 2*min_time)
	break;
    }
    switch_radius    = min_rad;
    mmm1d_params.far_switch_radius_2 = SQR(switch_radius);
    mmm1d_params.bessel_cutoff = determine_bessel_cutoff(switch_radius, mmm1d_params.maxPWerror, MAXIMAL_B_CUT);
    mmm1d_params.bessel_calculated = 1;
  }
  else if (mmm1d_params.bessel_cutoff < 0) {
    /* determine besselcutoff to achieve at least the given pairwise error */
    mmm1d_params.bessel_cutoff = determine_bessel_cutoff(sqrt(mmm1d_params.far_switch_radius_2),
							 mmm1d_params.maxPWerror, MAXIMAL_B_CUT);
    if (mmm1d_params.bessel_cutoff == MAXIMAL_B_CUT) {
      *log = strcat_alloc(*log, "could not find reasonable bessel cutoff");
      return ES_ERROR;
    }
    mmm1d_params.bessel_calculated = 1;
  }
  else
    mmm1d_params.bessel_calculated = 0;

  coulomb.method = COULOMB_MMM1D;

  mpi_bcast_coulomb_params();

  return ES_OK;
}
Ejemplo n.º 6
0
int scafacos_p3m_tuning(){
  
  int  mesh[3] = {0, 0, 0}, tmp_mesh_points; 
  int tmp_mesh[3];
  double r_cut_iL_min, r_cut_iL_max, r_cut_iL = -1, tmp_r_cut_iL=0.0;
  int cao;
  double                             alpha_L  = -1, tmp_alpha_L=0.0;
  double                             accuracy = -1, tmp_accuracy=0.0;
  double                            time_best=1e20, tmp_time;
  char b[3*ES_INTEGER_SPACE + 3*ES_DOUBLE_SPACE + 128];
  int buffer_cao, buffer_grid;
  double buffer_alpha_L, buffer_r_cut_iL, buffer_tolerance_field;
  
  if (skin == -1) {
//    *log = strcat_alloc(*log, "p3m cannot be tuned, since the skin is not yet set");
    return ES_ERROR;
  }

  
  /* preparation */
  mpi_bcast_event(FCS_P3M_COUNT_CHARGES);
  /* Print Status */
  sprintf(b, "P3M tune parameters: Accuracy goal = %.5e\n", scafacos_p3m.params.tolerance_field);
 // *log = strcat_alloc(*log, b);
  sprintf(b, "System: box_l = %.5e # charged part = %d Sum[q_i^2] = %.5e\n", box_l[0], scafacos_p3m.sum_qpart, scafacos_p3m.sum_q2);
//  *log = strcat_alloc(*log, b);

  if (scafacos_p3m.sum_qpart == 0) {
  //  *log = strcat_alloc(*log, "no charged particles in the system, cannot tune P3M");
    return ES_ERROR;
  }
  double density, r_cut;
  density = n_total_particles /(box_l[0]* box_l[1]* box_l[2]);
  int number = 100;
  r_cut= pow(number/ density/3.14 *3 /4 , 1/3.0);
  if(scafacos_p3m.params.r_cut_iL == 0.0) {
    // WARNING: r_cut_iL_min should not be small !

    r_cut_iL_min = dmin(min_local_box_l, min_box_l/2);
    r_cut_iL_min *= 0.18;
    r_cut_iL_min = r_cut *0.8;
    r_cut_iL_max = dmin(min_local_box_l, min_box_l/2);
    r_cut_iL_max *= 0.28;
    r_cut_iL_max = r_cut *1.5;
    if(r_cut_iL_max >= 4.5)
      r_cut_iL_max = 4.5;
//    r_cut_iL_max = dmin(min_local_box_l, min_box_l/2);// - skin;

//    r_cut_iL_min *= box_l_i[0];
//    r_cut_iL_max *= box_l_i[0];
    fprintf(stderr, "r_cut_iL_max: %f r_cut_iL_min: %f \n", r_cut_iL_max, r_cut_iL_min);
    fprintf(stderr, "box_l is: %f \n", box_l[0]);
  }
  else{
    fprintf(stderr, "Scafacos_p3m tuning varies the cutoff radius; you have to leave cutoff unspecified");
    return ES_ERROR;
  }
  
 // *log = strcat_alloc(*log, "mesh cao r_cut_iL     alpha_L      err          rs_err     ks_err     time [ms]\n");



  for(tmp_r_cut_iL = r_cut_iL_min; tmp_r_cut_iL <= r_cut_iL_max; tmp_r_cut_iL += 0.1){
    scafacos_p3m.params.cutoff = tmp_r_cut_iL;
    
    tmp_time = time_force_calc(1);
//    *log = strcat_alloc(*log, " %f ms ");
    fprintf(stderr, "time: %f \n", tmp_time);
//    *log = strcat_alloc(*log, b);
    
    if ((tmp_time < time_best) && (tmp_time > 0)) {
      time_best = tmp_time;
      fcs_p3m_get_grid(fcs_handle, &buffer_grid);
      fcs_p3m_get_cao(fcs_handle, &buffer_cao);
      fcs_p3m_get_r_cut(fcs_handle, &buffer_r_cut_iL);
      fcs_p3m_get_alpha(fcs_handle, &buffer_alpha_L);
      fcs_p3m_get_tolerance_field(fcs_handle, &buffer_tolerance_field);
      // target accuracy remains the same
    }
    /* no hope of further optimisation */
    //else if (tmp_time > time_best + P3M_TIME_GRAN) {
    //  break;
    //}
  }
  
  
  if(time_best == 1e20) {
    fprintf(stderr, "failed to tune P3M parameters to required accuracy\n");
    return ES_ERROR;
  }

  /* prepare tuned p3m parameters for broadcast*/
  scafacos_p3m.params.cao = buffer_cao;
  scafacos_p3m.params.alpha_L = buffer_alpha_L;
  scafacos_p3m.params.grid = buffer_grid;
  scafacos_p3m.params.cutoff = buffer_r_cut_iL;
  scafacos_p3m.params.alpha_L = buffer_alpha_L;
  /* Tell the user about the outcome */
  fprintf(stderr, "\nresulting parameters:\n%-4d %-3d %.5e %.5e %.5e %-8d\n", buffer_grid, buffer_cao, buffer_r_cut_iL, buffer_alpha_L, buffer_tolerance_field, (int)time_best);
  return ES_OK;
}