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