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