FLOAT_TYPE p3m_k_space_error_ik_i ( system_t *s, parameters_t *p ) { int nx, ny, nz; FLOAT_TYPE he_q = 0.0; FLOAT_TYPE alias1, alias2, alias3, alias4, n2; int mesh = p->mesh; he_q = p3m_find_error(p->alpha*s->length, mesh, p->cao, 1); if(he_q < 0) { he_q = 0.0; for ( nx=-mesh/2; nx<mesh/2; nx++ ) { for ( ny=-mesh/2; ny<mesh/2; ny++ ) { for ( nz=-mesh/2; nz<mesh/2; nz++ ) { if ( ( nx!=0 ) || ( ny!=0 ) || ( nz!=0 ) ) { n2 = SQR ( nx ) + SQR ( ny ) + SQR ( nz ); p3m_tune_aliasing_sums_ik_i ( nx,ny,nz, s, p, &alias1,&alias2,&alias3, &alias4 ); he_q += alias1 - SQR ( alias2 ) / (0.5*n2*(SQR(alias3)+SQR(alias4)) ); } } } } he_q = FLOAT_ABS(he_q); } return 2.0*s->q2*SQRT ( he_q/ ( FLOAT_TYPE ) s->nparticles ) / ( SQR ( s->length ) ); }
int main ( int argc, char **argv ) { int methodnr; FLOAT_TYPE alphamin,alphamax,alphastep; FLOAT_TYPE alpha; FLOAT_TYPE wtime; FILE* fout; system_t *system; method_t method; parameters_t parameters, parameters_ewald; data_t *data, *data_ewald; forces_t *forces, *forces_ewald; char *pos_file = NULL, *force_file = NULL, *out_file = NULL, *ref_out = NULL, *sys_out = NULL, *rdf_file = NULL, *vtf_file = NULL, *cdf_file = NULL; error_t error; FLOAT_TYPE length, prec; int npart; FLOAT_TYPE charge; int form_factor; FLOAT_TYPE rdf_min, rdf_max; int rdf_bins; FLOAT_TYPE error_k=0.0, ewald_error_k_est, estimate=0.0, error_k_est; int i,j, calc_k_error, calc_est; #ifdef _OPENMP int nthreads; #endif cmd_parameters_t params = { NULL, 0, NULL, 0 }; add_param( "rcut", ARG_TYPE_FLOAT, ARG_REQUIRED, &(parameters.rcut), ¶ms ); add_param( "alphamin", ARG_TYPE_FLOAT, ARG_OPTIONAL, &alphamin, ¶ms ); add_param( "alphamax", ARG_TYPE_FLOAT, ARG_OPTIONAL, &alphamax, ¶ms ); add_param( "alphastep", ARG_TYPE_FLOAT, ARG_OPTIONAL, &alphastep, ¶ms ); add_param( "alpha", ARG_TYPE_FLOAT, ARG_OPTIONAL, &alpha, ¶ms ); add_param( "positions", ARG_TYPE_STRING, ARG_OPTIONAL, &pos_file, ¶ms ); add_param( "error_k", ARG_TYPE_NONE, ARG_OPTIONAL, NULL, ¶ms ); add_param( "forces", ARG_TYPE_STRING, ARG_OPTIONAL, &force_file, ¶ms ); add_param( "mesh", ARG_TYPE_INT, ARG_REQUIRED, &(parameters.mesh), ¶ms ); add_param( "cao", ARG_TYPE_INT, ARG_REQUIRED, &(parameters.cao), ¶ms ); add_param( "method", ARG_TYPE_INT, ARG_REQUIRED, &methodnr, ¶ms ); add_param( "mc", ARG_TYPE_INT, ARG_OPTIONAL, &P3M_BRILLOUIN, ¶ms ); add_param( "mc_est", ARG_TYPE_INT, ARG_OPTIONAL, &P3M_BRILLOUIN_TUNING, ¶ms ); add_param( "no_estimate", ARG_TYPE_NONE, ARG_OPTIONAL, NULL, ¶ms ); add_param( "outfile", ARG_TYPE_STRING, ARG_OPTIONAL, &out_file, ¶ms ); add_param( "particles", ARG_TYPE_INT, ARG_OPTIONAL, &npart, ¶ms ); add_param( "box", ARG_TYPE_FLOAT, ARG_OPTIONAL, &length, ¶ms ); add_param( "tune", ARG_TYPE_NONE, ARG_OPTIONAL, NULL, ¶ms ); add_param( "prec", ARG_TYPE_FLOAT, ARG_OPTIONAL, &prec, ¶ms ); add_param( "reference_out", ARG_TYPE_STRING, ARG_OPTIONAL, &ref_out, ¶ms ); add_param( "system_out", ARG_TYPE_STRING, ARG_OPTIONAL, &sys_out, ¶ms ); add_param( "verlet_lists", ARG_TYPE_NONE, ARG_OPTIONAL, NULL, ¶ms ); add_param( "charge", ARG_TYPE_FLOAT, ARG_OPTIONAL, &charge, ¶ms ); add_param( "system_type", ARG_TYPE_INT, ARG_OPTIONAL, &form_factor, ¶ms ); add_param( "rdf", ARG_TYPE_STRING, ARG_OPTIONAL, &rdf_file, ¶ms ); add_param( "rdf_bins", ARG_TYPE_INT, ARG_OPTIONAL, &rdf_bins, ¶ms ); add_param( "rdf_rmin", ARG_TYPE_FLOAT, ARG_OPTIONAL, &rdf_min, ¶ms ); add_param( "rdf_rmax", ARG_TYPE_FLOAT, ARG_OPTIONAL, &rdf_max, ¶ms ); add_param( "cdf", ARG_TYPE_STRING, ARG_OPTIONAL, &cdf_file, ¶ms ); add_param( "no_calculation", ARG_TYPE_NONE, ARG_OPTIONAL, NULL, ¶ms ); add_param( "vtf_file", ARG_TYPE_STRING, ARG_OPTIONAL, &vtf_file, ¶ms ); add_param( "rdf_species", ARG_TYPE_NONE, ARG_OPTIONAL, NULL, ¶ms ); add_param( "no_reference_force", ARG_TYPE_NONE, ARG_OPTIONAL, NULL, ¶ms); #ifdef _OPENMP add_param( "threads", ARG_TYPE_INT, ARG_OPTIONAL, &nthreads, ¶ms ); #endif parse_parameters( argc - 1, argv + 1, params ); calc_k_error = param_isset( "error_k", params ); calc_est = param_isset( "estimate", params ); parameters.cao3 = parameters.cao*parameters.cao*parameters.cao; parameters.ip = parameters.cao - 1; parameters.alpha = 0.0; parameters_ewald = parameters; #ifdef _OPENMP if(param_isset("threads", params)) { omp_set_num_threads(nthreads); } printf("OpenMP: Using up to %d threads.\n", omp_get_max_threads( )); #endif if(!(param_isset("alphamin", params) && param_isset("alphamax", params) && param_isset("alphastep", params)) && !param_isset("alpha", params)) { puts("Need to provide either alpha-range (alphamin, alphamax, alphastep) or alpha."); exit(1); } if( !(param_isset("positions", params) == 1) && !((param_isset("box", params) == 1) && (param_isset("particles", params))) ) { puts("Need to provide either 'positions' or 'box' and 'particles'."); exit(1); } if( param_isset("positions", params) == 1) { // Inits the system and reads particle data and parameters from file. puts("Reading file"); system = Read_system ( ¶meters, pos_file ); puts("Done."); } else { puts("Generating system."); if( !(param_isset("charge", params) == 1)) { charge=1.0; } if(param_isset("system_type", params)) { printf("Using system type %d\n", form_factor); system = generate_system( form_factor, npart, length, charge); } else { system = generate_system( FORM_FACTOR_RANDOM, npart, length, charge); } puts("Done."); } if( param_isset("vtf_file", params) == 1) write_vtf( vtf_file, system ); if( param_isset("rdf", params) == 1) { puts("Calculating RDF"); if( param_isset("rdf_bins", params) == 0) rdf_bins = 100; if( param_isset("rdf_rmin", params) == 0) rdf_min = 0.0; if( param_isset("rdf_rmax", params) == 0) rdf_max = system->length/2; printf("Using %d bins, %lf <= r <= %lf\n", rdf_bins, rdf_min, rdf_max); int bins = rdf_bins; FLOAT_TYPE *rdf = radial_distribution(rdf_min, rdf_max, rdf_bins, system); FLOAT_TYPE *c; /* FLOAT_TYPE *rdf_sym = Init_array( 2*bins-1, 2*sizeof(FLOAT_TYPE)); */ /* c = low_pass_forward( bins, rdf, 0.3); */ /* c = low_pass_backward(bins, c, 0.3); */ /* rdf = c; */ /* for(int i = 0; i < 2*bins; i++) { */ /* rdf_sym[i] = c[i]; */ /* } */ /* for(int i = bins; i < 2*bins-1; i++) { */ /* rdf_sym[2*i] = c[2*bins - 2] + (i-bins)*(c[2] - c[0]); */ /* rdf_sym[2*i+1] = c[4*bins - 2*i - 1]; */ /* } */ FILE *rdf_out = fopen(rdf_file, "w"); /* FILE *c_out = fopen("c_fft.dat", "w"); */ /* rshif_array(2*(2*bins-1), c, 2*bins); */ for(int i = 0; i<bins; i++) fprintf(rdf_out, "%e %e\n", FLOAT_CAST rdf[2*i], FLOAT_CAST rdf[2*i+1]); /* for(int i = 0; i<2*bins-1; i++) */ /* /\* fprintf(c_out, "%e %e\n", FLOAT_CAST rdf_sym[2*i], FLOAT_CAST rdf_sym[2*i+1] ); *\/ */ /* fprintf(c_out, "%d %e %e\n", i, FLOAT_CAST c[2*i], FLOAT_CAST c[2*i+1] ); */ /* fclose(c_out); */ fclose(rdf_out); fftw_free(rdf); /* fftw_free(c); */ puts("Done."); } if( param_isset("rdf_species", params) == 1) { radial_distribution_species(0.0, 3.0, 200, system); } forces = Init_forces(system->nparticles); forces_ewald = Init_forces(system->nparticles); if(param_isset("reference_out", params)) { printf("Minimal distance: %.*f\n", DIGITS, FLOAT_CAST Min_distance( system )); puts("Calculating reference forces."); printf("Reference precision %e\n.", FLOAT_CAST Calculate_reference_forces( system, ¶meters )); puts("Done."); printf("Writing reference forces to '%s'\n", ref_out); Write_exact_forces(system, ref_out); puts("Done."); } if(param_isset("system_out", params)) { printf("Writing system to '%s'\n", sys_out); Write_system(system, sys_out); puts("Done."); } if(param_isset("no_calculation", params) == 1) return 0; if(param_isset("forces", params) == 1) { printf("Reading reference forces from '%s'.\n", force_file); Read_exact_forces( system, force_file ); puts("Done."); } else { if(param_isset("no_reference_force", params) !=1) { puts("Calculating reference forces."); printf("Reference precision %e\n.", FLOAT_CAST Calculate_reference_forces( system, ¶meters )); puts("Done."); } else { puts("Skipping reference force calculation."); } } if ( methodnr == method_ewald.method_id ) method = method_ewald; #ifdef P3M_IK_H else if ( methodnr == method_p3m_ik.method_id ) method = method_p3m_ik; #endif #ifdef P3M_IK_I_H else if ( methodnr == method_p3m_ik_i.method_id ) method = method_p3m_ik_i; #endif #ifdef P3M_AD_H else if ( methodnr == method_p3m_ad.method_id ) method = method_p3m_ad; #endif #ifdef P3M_AD_I_H else if ( methodnr == method_p3m_ad_i.method_id ) { method = method_p3m_ad_i; } #endif else { fprintf ( stderr, "Method %d not know.", methodnr ); exit ( 126 ); } if ( ( method.Init == NULL ) || ( method.Influence_function == NULL ) || ( method.Kspace_force == NULL ) ) { fprintf ( stderr,"Internal error: Method '%s' (%d) is not properly defined. Aborting.\n", method.method_name, method.method_id ); exit ( -1 ); } fprintf ( stderr, "Using %s.\n", method.method_name ); if(param_isset("outfile", params) == 1) { fout = fopen ( out_file, "w" ); } else { fout = fopen ( "out.dat","w" ); } printf ( "Init" ); fflush(stdout); data = method.Init ( system, ¶meters ); printf ( ".\n" ); printf ( "Init Ewald" ); data_ewald = method_ewald.Init ( system, ¶meters_ewald ); printf ( ".\n" ); /* printf ( "Init neighborlist" ); */ /* Init_neighborlist ( system, ¶meters, data ); */ /* printf ( ".\n" ); */ FLOAT_TYPE gen_err_dip, gen_err; printf ( "# %8s\t%8s\t%8s\t%8s\t%8s\n", "alpha", "DeltaF", "Estimate", "R-Error-Est", "K-Error-Est Generic-K-Space-err" ); for ( parameters.alpha=alphamin; parameters.alpha<=alphamax; parameters.alpha+=alphastep ) { parameters_ewald.alpha = parameters.alpha; method.Influence_function ( system, ¶meters, data ); /* Hockney/Eastwood */ wtime = MPI_Wtime(); Calculate_forces ( &method, system, ¶meters, data, forces ); /* Hockney/Eastwood */ wtime = MPI_Wtime() - wtime; error_k =0.0; if(calc_k_error == 1) { puts("kerror"); for(i=0;i<3;i++) { memset ( forces_ewald->f_k->fields[i], 0, system->nparticles*sizeof ( FLOAT_TYPE ) ); } method_ewald.Influence_function ( system, ¶meters_ewald, data_ewald ); method_ewald.Kspace_force( system, ¶meters_ewald, data_ewald, forces_ewald ); error_k =0.0; for (i=0; i<system->nparticles; i++) { for (j=0;j<3;j++) { /* printf("f_k_p3m [%lf, %lf, %lf] f_k_ewald [%lf, %lf %lf]\n", */ /* forces->f_k->fields[0][i],forces->f_k->fields[1][i],forces->f_k->fields[2][i], */ /* forces_ewald->f_k->fields[0][i],forces_ewald->f_k->fields[1][i],forces_ewald->f_k->fields[2][i]); */ error_k += SQR( forces->f_k->fields[j][i] - forces_ewald->f_k->fields[j][i] ); } } error_k = SQRT(error_k) / SQRT(system->nparticles); } ewald_error_k_est = compute_error_estimate_k( system, ¶meters_ewald, parameters_ewald.alpha); error = Calculate_errors ( system, forces ); if ( method.Error != NULL ) { if( calc_est == 0 ) estimate = method.Error ( system, ¶meters ); error_k_est = method.Error_k ( system, ¶meters); FLOAT_TYPE Q_uncorr, Q_corr, Q_nonfluc; /* Q_uncorr = Generic_error_estimate( A_ad, B_ad, C_ewald, system, ¶meters, data); */ /* Q_corr = Generic_error_estimate( A_ad_water, B_ad_water, C_ewald_water, system, ¶meters, data); */ FLOAT_TYPE corrected_est, corrected_total, rs_error; corrected_est = system->q2 / (system->length * SQR(system->length)) * SQRT( ( Q_uncorr - Q_corr ) / system->nparticles ); gen_err = system->q2 / (system->length * SQR(system->length)) * SQRT( ( Q_uncorr ) / system->nparticles ); gen_err_dip = ((Q_corr > 0) - (Q_corr < 0)) * system->q2 / (system->length * SQR(system->length)) * SQRT( ( FLOAT_ABS(Q_corr) ) / system->nparticles ); rs_error =Realspace_error( system, ¶meters ); corrected_total = SQRT( SQR(rs_error) + SQR(corrected_est)); /* printf("Q_uncorr %e, Q_corr %e, Q_nonfluc %e\n", Q_uncorr, Q_corr, Q_nonfluc); */ printf ( "%8lf\t%8e\t%8e\t %8e %8e\t %8e sec\t %8e\t %e\t %e\n", FLOAT_CAST parameters.alpha, FLOAT_CAST (error.f / SQRT(system->nparticles)) , FLOAT_CAST estimate, FLOAT_CAST rs_error , FLOAT_CAST error_k_est, FLOAT_CAST wtime, FLOAT_CAST gen_err, FLOAT_CAST gen_err_dip, FLOAT_CAST corrected_total ); /* printf ( "%8lf\t%8e\t%8e\t %8e %8e\t %8e sec\n", FLOAT_CAST parameters.alpha, FLOAT_CAST (error.f / SQRT(system->nparticles)) , FLOAT_CAST estimate, */ /* FLOAT_CAST rs_error , FLOAT_CAST error_k_est, FLOAT_CAST wtime ); */ fprintf ( fout,"% lf\t% e\t% e\t% e\t% e\t% e\t% e\t% e\n", FLOAT_CAST parameters.alpha, FLOAT_CAST (error.f / SQRT(system->nparticles)) , FLOAT_CAST estimate, FLOAT_CAST Realspace_error( system, ¶meters ), FLOAT_CAST error_k_est, FLOAT_CAST error_k, FLOAT_CAST ewald_error_k_est, FLOAT_CAST corrected_total); } else { printf ( "%8lf\t%8e\t na\t%8e\t%8e\n", FLOAT_CAST parameters.alpha, FLOAT_CAST error.f / system->nparticles , FLOAT_CAST error.f_r, FLOAT_CAST error.f_k ); fprintf ( fout,"% lf\t% e\t na\n", FLOAT_CAST parameters.alpha, FLOAT_CAST error.f / system->nparticles ); } #ifdef FORCE_DEBUG fprintf ( stderr, "%lf rms %e %e %e\n", parameters.alpha, error.f_v[0], error.f_v[1], error.f_v[2] ); #endif fflush ( stdout ); fflush ( fout ); } fclose ( fout ); return 0; }