Пример #1
0
int dipolar_set_Dbjerrum(double bjerrum)
{
  if (bjerrum < 0.0)
    return ES_ERROR;
  
  coulomb.Dbjerrum = bjerrum;

  if (coulomb.Dbjerrum == 0.0) {
    switch (coulomb.Dmethod) {
#ifdef DP3M
    case DIPOLAR_MDLC_P3M:
      // fall through
    case DIPOLAR_P3M:
      coulomb.Dbjerrum = bjerrum;
      dp3m_set_bjerrum();
      break;
#endif
    }
 
    mpi_bcast_coulomb_params();
    coulomb.Dmethod = DIPOLAR_NONE;
    mpi_bcast_coulomb_params();

  }

  return ES_OK;
}
Пример #2
0
int dipolar_set_Dbjerrum(double bjerrum)
{
  if (bjerrum < 0.0)
    return ES_ERROR;
  
  coulomb.Dbjerrum = bjerrum;

  if (coulomb.Dbjerrum == 0.0) {
    switch (coulomb.Dmethod) {
#ifdef DP3M
    case DIPOLAR_MDLC_P3M:
      // fall through
    case DIPOLAR_P3M:
      coulomb.Dbjerrum = bjerrum;
      dp3m_set_bjerrum();
      break;
#endif
    case DIPOLAR_SCAFACOS: ;
      // Fall through 
    default:
        break;
    }
 
    mpi_bcast_coulomb_params();
    set_dipolar_method_local(DIPOLAR_NONE);
    mpi_bcast_coulomb_params();

  }

  return ES_OK;
}
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;
}
Пример #4
0
int ewald_set_params(double r_cut, double alpha, int kmax)
{
  if(r_cut < 0)
    return -1;

  ewald.r_cut    = r_cut;
  ewald.r_cut_iL = r_cut*box_l_i[0];

  if (alpha > 0) {
    ewald.alpha   = alpha;
    ewald.alpha_L = alpha*box_l[0];
  }
  else
    if (alpha != -1.0)
      return -4;

  if (kmax > 0) {
    ewald.kmax = kmax;
    ewald.kmaxsq = kmax*kmax;
  }
  else return -5;

  mpi_bcast_coulomb_params();

  return 0;
}
Пример #5
0
int tclcommand_inter_parse_scafacos(Tcl_Interp *interp, int argc, char ** argv) {
  if(argc < 1)
    return TCL_ERROR;

  // Scafacos can be used either for charges or for dipoles, not for both.
  if (dipolar) {
    if (coulomb.method==COULOMB_SCAFACOS) {
      runtimeErrorMsg() << "Scafacos already in use for charges.";
      return TCL_ERROR;
    }
  }
  else 
  {
    #ifdef SCAFACOS_DIPOLES
    if (coulomb.Dmethod==DIPOLAR_SCAFACOS) {
      runtimeErrorMsg() << "Scafacos already in use for dipoles.";
      return TCL_ERROR;
    }
    #endif
  }





  
  const std::string method(argv[0]);
  
  std::stringstream params;

  if(argc > 1) {
    for(int i = 1; i < argc; i++) {
      params << std::string(argv[i]);
      if(i != (argc-1))
        params << ",";
    }
  }

  // Coulomb ia
  if (! dipolar)
  {
    coulomb.method  = COULOMB_SCAFACOS;
  }
  else
  // Dipolar interaction
  {
    #ifdef SCAFACOS_DIPOLES
      coulomb.Dmethod  = DIPOLAR_SCAFACOS;
    #else
      runtimeErrorMsg() << "Dipolar support for SCAFACOS not compiled in. Activate via SCAFACOS_DIPOLES in myconfig.hpp.";
    #endif
  }

  mpi_bcast_coulomb_params();
  Scafacos::set_parameters(method, params.str(),dipolar);


  
  return TCL_OK;
}
Пример #6
0
/* TODO: This function is not used anywhere. To be removed?  */
int ewald_set_eps(double eps)
{
  ewald.epsilon = eps;

  mpi_bcast_coulomb_params();

  return TCL_OK;
}
int MMM1D_set_params(double switch_rad, double maxPWerror)
{
  mmm1d_params.far_switch_radius_2 = (switch_rad > 0) ? SQR(switch_rad) : -1;
  mmm1d_params.maxPWerror = maxPWerror;
  coulomb.method = COULOMB_MMM1D;

  mpi_bcast_coulomb_params();

  return 0;
}
Пример #8
0
int coulomb_set_bjerrum(double bjerrum)
{
  if (bjerrum < 0.0)
    return ES_ERROR;
  
  coulomb.bjerrum = bjerrum;

  if (coulomb.bjerrum == 0.0) {
    switch (coulomb.method) {
#ifdef P3M
    case COULOMB_ELC_P3M:
    case COULOMB_P3M_GPU:
    case COULOMB_P3M:
      p3m_set_bjerrum();
      break;
#endif
    case COULOMB_DH:
      dh_params.r_cut   = 0.0;
      dh_params.kappa   = 0.0;
    case COULOMB_RF:
    case COULOMB_INTER_RF:
      rf_params.kappa  = 0.0;
      rf_params.epsilon1   = 0.0;
      rf_params.epsilon2   = 0.0;
      rf_params.r_cut   = 0.0;
      rf_params.B   = 0.0;
    case COULOMB_MMM1D:
      mmm1d_params.maxPWerror = 1e40;
    default: break;
    }
 
    mpi_bcast_coulomb_params();
    coulomb.method = COULOMB_NONE;
    mpi_bcast_coulomb_params();

  }

  return ES_OK;
}
int dawaanr_set_params()
{
  if (n_nodes > 1) {
    return ES_ERROR;
  }
  if (coulomb.Dmethod != DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA ) {
    coulomb.Dmethod = DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA;
  } 
  // also necessary on 1 CPU, does more than just broadcasting
  mpi_bcast_coulomb_params();

  return ES_OK;
}
Пример #10
0
int dh_set_params(double kappa, double r_cut)
{
  if(dh_params.kappa < 0.0)
    return -1;

  if(dh_params.r_cut < 0.0)
    return -2;

  dh_params.kappa = kappa;
  dh_params.r_cut = r_cut;

  mpi_bcast_coulomb_params();

  return 1;
}
Пример #11
0
int MMM1D_set_params(double switch_rad, int bessel_cutoff, double maxPWerror)
{
  MMM1D_setup_constants();

  mmm1d_params.far_switch_radius_2 = (switch_rad > 0) ? SQR(switch_rad) : -1;
  mmm1d_params.bessel_cutoff = bessel_cutoff;
  /* if parameters come from here they are never calculated that is
     only the case if you call mmm1d_tune, which then
     changes this flag */
  mmm1d_params.bessel_calculated = 0;

  mmm1d_params.maxPWerror = maxPWerror;
  coulomb.method = COULOMB_MMM1D;

  mpi_bcast_coulomb_params();

  return 0;
}
int mdds_set_params(int n_cut)
{
  if (n_nodes > 1) {
    return ES_ERROR;  
  }
  
  Ncut_off_magnetic_dipolar_direct_sum = n_cut;
  
  if (Ncut_off_magnetic_dipolar_direct_sum == 0) {
    fprintf(stderr,"Careful:  the number of extra replicas to take into account during the direct sum calculation is zero \n");
  }
  
  if (coulomb.Dmethod != DIPOLAR_DS  && coulomb.Dmethod != DIPOLAR_MDLC_DS) {
    coulomb.Dmethod = DIPOLAR_DS;
  }  
  
  // also necessary on 1 CPU, does more than just broadcasting
  mpi_bcast_coulomb_params();
  return ES_OK;
}
Пример #13
0
int mdlc_set_params(double maxPWerror, double gap_size, double far_cut)
{
  MDLC_TRACE(fprintf(stderr, "%d: mdlc_set_params().\n", this_node));
  
  dlc_params.maxPWerror = maxPWerror;
  dlc_params.gap_size = gap_size;
  dlc_params.h = box_l[2] - gap_size;

  
  switch (coulomb.Dmethod) {
#ifdef DP3M
  case  DIPOLAR_MDLC_P3M:
  case  DIPOLAR_P3M:
    coulomb.Dmethod =DIPOLAR_MDLC_P3M;
    break;
#endif  
  case  DIPOLAR_MDLC_DS:
  case  DIPOLAR_DS: 
    coulomb.Dmethod =DIPOLAR_MDLC_DS; 
    break;
  default:
    return ES_ERROR;
  }

  dlc_params.far_cut = far_cut;
  if (far_cut != -1) {
    dlc_params.far_calculated = 0;
  }
  else {
    dlc_params.far_calculated = 1;
    if (mdlc_tune(dlc_params.maxPWerror) == ES_ERROR) {
      char *errtxt = runtime_error(128);
      ERROR_SPRINTF(errtxt, "{009 mdlc tuning failed, gap size too small} ");
    }
  }
  mpi_bcast_coulomb_params();

  return ES_OK;
}
Пример #14
0
int mdlc_set_params(double maxPWerror, double gap_size, double far_cut)
{
  MDLC_TRACE(fprintf(stderr, "%d: mdlc_set_params().\n", this_node));
  
  dlc_params.maxPWerror = maxPWerror;
  dlc_params.gap_size = gap_size;
  dlc_params.h = box_l[2] - gap_size;
  
  switch (coulomb.Dmethod) {
#ifdef DP3M
  case  DIPOLAR_MDLC_P3M:
  case  DIPOLAR_P3M:
    set_dipolar_method_local(DIPOLAR_MDLC_P3M);
    break;
#endif  
  case  DIPOLAR_MDLC_DS:
  case  DIPOLAR_DS: 
    set_dipolar_method_local(DIPOLAR_MDLC_DS); 
    break;
  default:
    return ES_ERROR;
  }

  dlc_params.far_cut = far_cut;
  if (far_cut != -1) {
    dlc_params.far_calculated = 0;
  }
  else {
    dlc_params.far_calculated = 1;
    if (mdlc_tune(dlc_params.maxPWerror) == ES_ERROR) {
        ostringstream msg;
        msg <<"mdlc tuning failed, gap size too small";
        runtimeError(msg);
    }
  }
  mpi_bcast_coulomb_params();

  return ES_OK;
}
Пример #15
0
int tclcommand_inter_coulomb_parse_ewaldgpu_notune(Tcl_Interp * interp, int argc, char ** argv)
{
	double r_cut=-1;
	int num_kx=-1;
	int num_ky=-1;
	int num_kz=-1;
	double alpha=-1;
	IntList il;
	init_intlist(&il);

	if(argc < 3 || argc > 5) {
		Tcl_AppendResult(interp, "\nExpected: inter coulomb <bjerrum> ewaldgpu <r_cut> (<K_cut> | {<K_cut,x> <K_cut,y><K_cut,z>}) <alpha>",(char *) NULL);
		return TCL_ERROR;
	}
	if(! ARG_IS_D(0,r_cut))
	{
		Tcl_AppendResult(interp, "\n<r_cut> double expected", (char *) NULL);
		return TCL_ERROR;
	}
	if(! ARG_IS_I(1, num_kx))
	{
		if( ! ARG_IS_INTLIST(1, il) || !(il.n == 3) )
		{
			Tcl_AppendResult(interp, "\n(<K_cut> | {<K_cut,x> <K_cut,y><K_cut,z>}) integer or integer list of length 3 expected", (char *) NULL);
			return TCL_ERROR;
		}
		else
		{
			num_kx = il.e[0];
			num_ky = il.e[1];
			num_kz = il.e[2];
		}
	}
	else
	{
		num_kz = num_ky = num_kx;
	}
	if(argc > 2)
	{
		if(! ARG_IS_D(2, alpha))
		{
			Tcl_AppendResult(interp, "\n<alpha> double expected", (char *) NULL);
			return TCL_ERROR;
		}
	}
	else
	{
		Tcl_AppendResult(interp, "\nAutomatic ewaldgpu tuning not implemented.",
				 (char *) NULL);
		return TCL_ERROR;
	}

	//Turn on ewaldgpu
	if (!ewaldgpuForce) // inter coulomb ewaldgpu was never called before
	{
		ewaldgpuForce = new EwaldgpuForce(espressoSystemInterface, r_cut, num_kx, num_ky, num_kz, alpha);
		forceActors.add(ewaldgpuForce);
		energyActors.add(ewaldgpuForce);
	}
	//Broadcast parameters
	ewaldgpuForce->set_params(r_cut, num_kx, num_ky, num_kz, alpha);
	coulomb.method = COULOMB_EWALD_GPU;
	ewaldgpu_params.isTunedFlag = false;
	ewaldgpu_params.isTuned = true;
	rebuild_verletlist = 1;
	mpi_bcast_coulomb_params();
	return TCL_OK;
}
Пример #16
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;
}
Пример #17
0
int tclcommand_inter_parse_magnetic(Tcl_Interp * interp, int argc, char ** argv)
{
  double d1;

  Tcl_ResetResult(interp);

  if(argc == 0) {
    tclprint_to_result_DipolarIA(interp);
    return TCL_OK;
  }
  
  if (! ARG0_IS_D(d1)) {
    Tcl_ResetResult(interp);
    
    if (ARG0_IS_S("mdlc") && ((coulomb.Dmethod == DIPOLAR_DS) || (coulomb.Dmethod == DIPOLAR_MDLC_DS)))
      return tclcommand_inter_magnetic_parse_mdlc_params(interp, argc - 1, argv + 1);

#ifdef DP3M
    if (ARG0_IS_S("mdlc") && ((coulomb.Dmethod == DIPOLAR_P3M) || (coulomb.Dmethod == DIPOLAR_MDLC_P3M)))
      return tclcommand_inter_magnetic_parse_mdlc_params(interp, argc - 1, argv + 1);
    
    if (coulomb.Dmethod == DIPOLAR_P3M)
      return tclcommand_inter_magnetic_parse_dp3m_opt_params(interp, argc, argv);
    else {
      Tcl_AppendResult(interp, "expect: inter magnetic <Dbjerrum>",
		       (char *) NULL);
      return TCL_ERROR;
    }
#else
    return TCL_ERROR;
#endif
  }


  if (dipolar_set_Dbjerrum(d1) == TCL_ERROR) {
    Tcl_AppendResult(interp, argv[0], "Dbjerrum length must be positive",
		     (char *) NULL);
    return TCL_ERROR;
  }
    
  argc -= 1;
  argv += 1;

  if (d1 == 0.0 && argc == 0) {
    mpi_bcast_coulomb_params();
    return TCL_OK;
  }

  if(argc < 1) {
    Tcl_AppendResult(interp, "wrong # args for inter magnetic.",
		     (char *) NULL);
    mpi_bcast_coulomb_params();
    return TCL_ERROR;
  }

  /* check method */

#define REGISTER_DIPOLAR(name, parser)			\
  if(ARG0_IS_S(name))					\
    return parser(interp, argc-1, argv+1);

#ifdef DP3M
  REGISTER_DIPOLAR("p3m", tclcommand_inter_magnetic_parse_dp3m);
#endif

  REGISTER_DIPOLAR("dawaanr", tclcommand_inter_magnetic_parse_dawaanr);

  REGISTER_DIPOLAR("mdds", tclcommand_inter_magnetic_parse_mdds);


  /* fallback */
  coulomb.Dmethod  = DIPOLAR_NONE;
  coulomb.Dbjerrum = 0.0;

  mpi_bcast_coulomb_params();

  Tcl_AppendResult(interp, "do not know magnetic method \"",argv[0],
		   "\": magnetic switched off", (char *) NULL);
  
  return TCL_ERROR;
}
Пример #18
0
int tclcommand_inter_parse_coulomb(Tcl_Interp * interp, int argc, char ** argv)
{
  double d1;

  Tcl_ResetResult(interp);

  if(argc == 0) {
    tclprint_to_result_CoulombIA(interp);
    return TCL_OK;
  }
  
  if (! ARG0_IS_D(d1)) {
#ifdef P3M
    Tcl_ResetResult(interp);
    if (ARG0_IS_S("elc") && ((coulomb.method == COULOMB_P3M) || (coulomb.method == COULOMB_ELC_P3M)))
      return tclcommand_inter_coulomb_parse_elc_params(interp, argc - 1, argv + 1);
    if (coulomb.method == COULOMB_P3M)
      return tclcommand_inter_coulomb_parse_p3m_opt_params(interp, argc, argv);
    else {
      Tcl_AppendResult(interp, "expect: inter coulomb <bjerrum>",
		       (char *) NULL);
      return TCL_ERROR;
    }
#else
    return TCL_ERROR;
#endif
  }

  if (coulomb_set_bjerrum(d1) == TCL_ERROR) {
    Tcl_AppendResult(interp, argv[0], "bjerrum length must be positive",
		     (char *) NULL);
    return TCL_ERROR;
  }
    
  argc -= 1;
  argv += 1;

  if (d1 == 0.0 && argc == 0) {
    mpi_bcast_coulomb_params();
    return TCL_OK;
  }

  if(argc < 1) {
    Tcl_AppendResult(interp, "wrong # args for inter coulomb.",
		     (char *) NULL);
    mpi_bcast_coulomb_params();
    return TCL_ERROR;
  }

  /* check method */

#define REGISTER_COULOMB(name, parser)			\
  if(ARG0_IS_S(name))					\
    return parser(interp, argc-1, argv+1);

#ifdef P3M
  REGISTER_COULOMB("p3m", tclcommand_inter_coulomb_parse_p3m);
#endif

  REGISTER_COULOMB("dh", tclcommand_inter_coulomb_parse_dh);    

  if(ARG0_IS_S("rf")) return tclcommand_inter_coulomb_parse_rf(interp, argc-1, argv+1,COULOMB_RF);

  if(ARG0_IS_S("inter_rf")) return tclcommand_inter_coulomb_parse_rf(interp, argc-1, argv+1,COULOMB_INTER_RF);

  REGISTER_COULOMB("mmm1d", tclcommand_inter_coulomb_parse_mmm1d);

  REGISTER_COULOMB("mmm2d", tclcommand_inter_coulomb_parse_mmm2d);

  REGISTER_COULOMB("maggs", tclcommand_inter_coulomb_parse_maggs);

  REGISTER_COULOMB("memd", tclcommand_inter_coulomb_parse_maggs);

  /* fallback */
  coulomb.method  = COULOMB_NONE;
  coulomb.bjerrum = 0.0;

  mpi_bcast_coulomb_params();

  Tcl_AppendResult(interp, "do not know coulomb method \"",argv[0],
		   "\": coulomb switched off", (char *) NULL);
  
  return TCL_ERROR;
}
Пример #19
0
int tclcommand_inter_coulomb_parse_ewaldgpu(Tcl_Interp * interp, int argc, char ** argv)
{
	double r_cut;
	int num_kx;
	int num_ky;
	int num_kz;
	double accuracy;
	double alpha=-1;
	IntList il;
	init_intlist(&il);

  if (argc < 1)
  {
  	Tcl_AppendResult(interp, "expected: inter coulomb <bjerrum> ewaldgpu <r_cut> (<K_cut> | {<K_cut,x> <K_cut,y><K_cut,z>}) <alpha> \nexpected: inter coulomb <bjerrum> ewaldgpu tune <accuracy> [<precision>] \nexpected: inter coulomb <bjerrum> ewaldgpu tunealpha <r_cut> <K_cut> [<precision>]",(char *) NULL);
    return TCL_ERROR;
  }

  if (ARG0_IS_S("tune"))
  {
    int status = tclcommand_inter_coulomb_parse_ewaldgpu_tune(interp, argc-1, argv+1, 0);
    if(status==TCL_OK) return TCL_OK;
    if(status==TCL_ERROR)
    {
    	Tcl_AppendResult(interp, "Accuracy could not been reached. Choose higher K_max or lower accuracy",(char *) NULL);
    	    return TCL_ERROR;
    }

  }

  if (ARG0_IS_S("tunealpha"))
    return tclcommand_inter_coulomb_parse_ewaldgpu_tunealpha(interp, argc-1, argv+1);

  if(! ARG0_IS_D(r_cut))
    return TCL_ERROR;

  if(argc < 3 || argc > 5) {
  	Tcl_AppendResult(interp, "expected: inter coulomb <bjerrum> ewaldgpu <r_cut> (<K_cut> | {<K_cut,x> <K_cut,y><K_cut,z>}) <alpha> \nexpected: inter coulomb <bjerrum> ewaldgpu tune <accuracy> [<precision>] \nexpected: inter coulomb <bjerrum> ewaldgpu tunealpha <r_cut> <K_cut> [<precision>]",(char *) NULL);
    return TCL_ERROR;
  }

  if(! ARG_IS_I(1, num_kx))
  {
    if( ! ARG_IS_INTLIST(1, il) || !(il.n == 3) )
    {
      Tcl_AppendResult(interp, "integer or interger list of length 3 expected", (char *) NULL);
      return TCL_ERROR;
    }
    else
    {
      num_kx = il.e[0];
      num_ky = il.e[1];
      num_kz = il.e[2];
    }
  }
  else
  {
  	num_kz = num_ky = num_kx;
  }

  if(argc > 2)
  {
    if(! ARG_IS_D(2, alpha))
      return TCL_ERROR;
  }
  else
  {
    Tcl_AppendResult(interp, "Automatic ewaldgpu tuning not implemented.",
		     (char *) NULL);
    return TCL_ERROR;
  }

  if(argc > 3)
  {
    if(! ARG_IS_D(3, accuracy))
    {
      Tcl_AppendResult(interp, "accuracy double expected", (char *) NULL);
      return TCL_ERROR;
    }
  }

  // Create object
  EwaldgpuForce *A=new EwaldgpuForce(r_cut, num_kx, num_ky, num_kz, alpha);
  FI.addMethod(A);
  rebuild_verletlist = 1;
  ewaldgpu_params.ewaldgpu_is_running = true;
  ewaldgpu_params.isTuned = true;
	mpi_bcast_coulomb_params();
	mpi_bcast_event(INVALIDATE_SYSTEM);
  return TCL_OK;
}
Пример #20
0
int tclcommand_inter_coulomb_parse_ewaldgpu_tunealpha(Tcl_Interp * interp, int argc, char ** argv)
{
	double r_cut;
	double alpha;
	int num_kx;
	int num_ky;
	int num_kz;
	double precision=0.000001;

	IntList il;
	init_intlist(&il);

  if (argc < 3)
  {
    Tcl_AppendResult(interp, "wrong # arguments: <r_cut> <K_cut,x> <K_cut,y><K_cut,z> [<precision>]  ", (char *) NULL);
    return TCL_ERROR;
  }

  /* PARSE EWALD COMMAND LINE */
  /* epsilon */
  if (! ARG_IS_D(0, r_cut))
  {
    Tcl_AppendResult(interp, "<r_cut> should be a double",(char *) NULL);
  }
  /* k_cut */
  if(! ARG_IS_I(1, num_kx))
  {
    if( ! ARG_IS_INTLIST(1, il) || !(il.n == 3) )
    {
      Tcl_AppendResult(interp, "integer or integer list of length 3 expected", (char *) NULL);
      return TCL_ERROR;
    }
    else
    {
      num_kx = il.e[0];
      num_ky = il.e[1];
      num_kz = il.e[2];
    }
  }
  else
  {
  	num_kz = num_ky = num_kx;
  }
  /* precision */
  if (! ARG_IS_D(2, precision))
  {
    Tcl_AppendResult(interp, "<precision> should be a double",
		     (char *) NULL);
    return 0;
  }
  //Compute alpha
  double q_sqr = ewaldgpu_compute_q_sqare();
  alpha = ewaldgpu_compute_optimal_alpha(r_cut, num_kx, num_ky, num_kz, q_sqr, box_l, precision);
  ewaldgpu_params.isTuned = true;
  mpi_bcast_coulomb_params();
  mpi_bcast_event(INVALIDATE_SYSTEM);
  // Create object
  EwaldgpuForce *A=new EwaldgpuForce(r_cut, num_kx, num_ky, num_kz, alpha);
  FI.addMethod(A);
  rebuild_verletlist = 1;

  return TCL_OK;
}
Пример #21
0
int tclcommand_inter_coulomb_parse_ewaldgpu_tune(Tcl_Interp * interp, int argc, char ** argv, int adaptive)
{
	double r_cut;
	double alpha;
	int num_kx;
	int num_ky;
	int num_kz;
	int K_max = 30;
	int time_calc_steps = 0;
	double accuracy = 0.0001;
	double precision = 0.000001;

  while(argc > 0)
  {
    if(ARG0_IS_S("accuracy"))
    {
      if(! (argc > 1 && ARG1_IS_D(accuracy) && accuracy > 0))
      {
				Tcl_AppendResult(interp, "accuracy expects a positive double ",(char *) NULL);
				return TCL_ERROR;
      }
    }
    else if(ARG0_IS_S("precision"))
    {
      if(! (argc > 1 && ARG1_IS_D(precision) && precision > 0))
      {
				Tcl_AppendResult(interp, "precision expects a positive double ",(char *) NULL);
				return TCL_ERROR;
      }
    }
    else if(ARG0_IS_S("K_max"))
    {
      if(! (argc > 1 && ARG1_IS_I(K_max) && K_max > 0))
      {
				Tcl_AppendResult(interp, "K_max expects a positive integer ",(char *) NULL);
				return TCL_ERROR;
      }
    }
    else if(ARG0_IS_S("time_calc_steps"))
    {
      if(! (argc > 1 && ARG1_IS_I(time_calc_steps) && time_calc_steps > 0))
      {
				Tcl_AppendResult(interp, "time_calc_steps expects a positive integer ",(char *) NULL);
				return TCL_ERROR;
      }
    }
    /* unknown parameter. Probably one of the optionals */
    else break;

    argc -= 2;
    argv += 2;
  }

  ewaldgpu_set_params_tune(accuracy, precision, K_max, time_calc_steps);

  /* Create object */
  EwaldgpuForce *A=new EwaldgpuForce(r_cut, num_kx, num_ky, num_kz, alpha);
  FI.addMethod(A);
  rebuild_verletlist = 1;

  /* do the tuning */
  char *log = NULL;
  if (ewaldgpu_adaptive_tune(&log) == ES_ERROR)
  {
    Tcl_AppendResult(interp, log, "\nfailed to tune ewaldgpu parameters to required accuracy ", (char *) NULL);
    if (log) free(log);
    return TCL_ERROR;
  }

  /* Tell the user about the tuning outcome */
  Tcl_AppendResult(interp, log, (char *) NULL);
  if (log) free(log);

  rebuild_verletlist = 1;
	mpi_bcast_coulomb_params();
	mpi_bcast_event(INVALIDATE_SYSTEM);
  return TCL_OK;
}
Пример #22
0
int tclcommand_inter_coulomb_parse_ewaldgpu_tunealpha(Tcl_Interp * interp, int argc, char ** argv)
{
	double r_cut;
	double alpha;
	int num_kx;
	int num_ky;
	int num_kz;
	double precision=0.000001;
	IntList il;
	init_intlist(&il);

  //PARSE EWALD COMMAND LINE
  if (argc < 3)
  {
    Tcl_AppendResult(interp, "\nWrong # arguments: <r_cut> (<K_cut> | {<K_cut,x> <K_cut,y><K_cut,z>}) <precision>", (char *) NULL);
    return TCL_ERROR;
  }
  if (! ARG0_IS_D(r_cut))
  {
    Tcl_AppendResult(interp, "\n<r_cut> should be a double",(char *) NULL);
    return TCL_ERROR;
  }
  if(! ARG_IS_I(1, num_kx))
  {
    if( ! ARG_IS_INTLIST(1, il) || !(il.n == 3) )
    {
      Tcl_AppendResult(interp, "\n(<K_cut> | {<K_cut,x> <K_cut,y><K_cut,z>}) integer or integer list of length 3 expected", (char *) NULL);
      return TCL_ERROR;
    }
    else
    {
      num_kx = il.e[0];
      num_ky = il.e[1];
      num_kz = il.e[2];
    }
  }
  else
  {
  	num_kz = num_ky = num_kx;
  }
  if (! ARG_IS_D(2, precision))
  {
    Tcl_AppendResult(interp, "\n<precision> should be a double", (char *) NULL);
    return TCL_ERROR;
  }

  //Compute alpha
	Particle *particle;
	particle = (Particle*)Utils::malloc(n_part*sizeof(Particle));
	mpi_get_particles(particle, NULL);
	double q_sqr = ewaldgpuForce->compute_q_sqare(particle);
  alpha = ewaldgpuForce->compute_optimal_alpha(r_cut, num_kx, num_ky, num_kz, q_sqr, box_l, precision);

  //Turn on ewaldgpu
  if (!ewaldgpuForce) // inter coulomb ewaldgpu was never called before
  {
	  ewaldgpuForce = new EwaldgpuForce(espressoSystemInterface, r_cut, num_kx, num_ky, num_kz, alpha);
	  forceActors.add(ewaldgpuForce);
	  energyActors.add(ewaldgpuForce);
  }
  //Broadcast parameters
  coulomb.method = COULOMB_EWALD_GPU;
  ewaldgpu_params.isTunedFlag = false;
  ewaldgpu_params.isTuned = true;
  rebuild_verletlist = 1;
  mpi_bcast_coulomb_params();
  return TCL_OK;
}
Пример #23
0
int tclcommand_inter_coulomb_parse_ewaldgpu_tune(Tcl_Interp * interp, int argc, char ** argv, int adaptive)
{
	double r_cut=-1;
	double alpha=-1;
	int num_kx=-1;
	int num_ky=-1;
	int num_kz=-1;
	int K_max = 30;
	int time_calc_steps = 100;
	double accuracy = 0.0001;
	double precision = 0.000001;

	//PARSE EWALD COMMAND LINE
	while(argc > 0)
	{
		if(ARG0_IS_S("accuracy"))
		{
			if(! (argc > 1 && ARG1_IS_D(accuracy) && accuracy > 0))
			{
				Tcl_AppendResult(interp, "\n<accuracy> expects a positive double ",(char *) NULL);
				return TCL_ERROR;
			}
		}
		else if(ARG0_IS_S("precision"))
		{
			if(! (argc > 1 && ARG1_IS_D(precision) && precision > 0))
			{
				Tcl_AppendResult(interp, "\n<precision> expects a positive double ",(char *) NULL);
				return TCL_ERROR;
			}
		}
		else if(ARG0_IS_S("K_max"))
		{
			if(! (argc > 1 && ARG1_IS_I(K_max) && K_max > 0))
			{
				Tcl_AppendResult(interp, "\n<K_max> expects a positive integer ",(char *) NULL);
				return TCL_ERROR;
			}
		}
		else if(ARG0_IS_S("time_calc_steps"))
		{
			if(! (argc > 1 && ARG1_IS_I(time_calc_steps) && time_calc_steps > 0))
			{
				Tcl_AppendResult(interp, "\n<time_calc_steps> expects a positive integer ",(char *) NULL);
				return TCL_ERROR;
			}
		}
		else break;

		argc -= 2;
		argv += 2;
	}

  //Turn on ewaldgpu
  ewaldgpuForce->set_params_tune(accuracy, precision, K_max, time_calc_steps);
  if (!ewaldgpuForce) // inter coulomb ewaldgpu was never called before
  {
	  ewaldgpuForce = new EwaldgpuForce(espressoSystemInterface, r_cut, num_kx, num_ky, num_kz, alpha);
	  forceActors.add(ewaldgpuForce);
	  energyActors.add(ewaldgpuForce);
  }

  //Broadcast parameters
  coulomb.method = COULOMB_EWALD_GPU;
  ewaldgpu_params.isTunedFlag = false;
  rebuild_verletlist = 1;
  mpi_bcast_coulomb_params();
  //Tuning
  char *log = NULL;
  if (ewaldgpuForce->adaptive_tune(&log,espressoSystemInterface) == ES_ERROR)
  {
    Tcl_AppendResult(interp,  "\nAccuracy could not been reached. Choose higher K_max or lower accuracy", (char *) NULL);
    return TCL_ERROR;
  }
  //Tell the user about the tuning outcome
  Tcl_AppendResult(interp, log, (char *) NULL);
  if (log) free(log);

  return TCL_OK;
}
Пример #24
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;
}