/*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, haktulga@cs.purdue.edu Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #if (defined(HAVE_CONFIG_H) && !defined(__CONFIG_H_)) #define __CONFIG_H_ #include "../../common/include/config.h" #endif #if defined(PURE_REAX) #include "control.h" #include "tool_box.h" #elif defined(LAMMPS_REAX) #include "reax_control.h" #include "reax_tool_box.h" #endif void Read_Control_File( const char * const control_file, control_params * const control, output_controls * const out_control ) { FILE *fp; char *s, **tmp; int c, i, ival; real val; fp = sfopen( control_file, "r", "Read_Control_File::fp" ); /* assign default values */ strncpy( control->sim_name, "default.sim", sizeof(control->sim_name) - 1 ); control->sim_name[sizeof(control->sim_name) - 1] = '\0'; control->ensemble = NVE; control->nsteps = 0; control->dt = 0.25; control->nprocs = 1; control->procs_by_dim[0] = 1; control->procs_by_dim[1] = 1; control->procs_by_dim[2] = 1; control->geo_format = 1; control->gpus_per_node = 1; control->random_vel = 0; control->restart = 0; out_control->restart_format = WRITE_BINARY; out_control->restart_freq = 0; control->reposition_atoms = 0; control->restrict_bonds = 0; control->remove_CoM_vel = 25; out_control->debug_level = 0; out_control->energy_update_freq = 0; control->reneighbor = 1; control->bond_cut = 5.0; control->vlist_cut = control->nonb_cut; control->bg_cut = 0.3; control->thb_cut = 0.001; control->hbond_cut = 0.0; control->tabulate = 0; control->charge_method = QEQ_CM; control->charge_freq = 1; control->cm_q_net = 0.0; control->cm_solver_type = CG_S; control->cm_solver_max_iters = 1000; control->cm_solver_restart = 100; control->cm_solver_q_err = 0.000001; control->cm_domain_sparsify_enabled = FALSE; control->cm_init_guess_extrap1 = 3; control->cm_init_guess_extrap2 = 2; control->cm_domain_sparsity = 1.0; control->cm_solver_pre_comp_type = JACOBI_PC; control->cm_solver_pre_comp_sweeps = 3; control->cm_solver_pre_comp_refactor = 1; control->cm_solver_pre_comp_droptol = 0.01; control->cm_solver_pre_app_type = TRI_SOLVE_PA; control->cm_solver_pre_app_jacobi_iters = 50; control->polarization_energy_enabled = TRUE; control->T_init = 0.0; control->T_final = 300.; control->Tau_T = 500.0; control->T_mode = 0; control->T_rate = 1.0; control->T_freq = 1.0; control->P[0] = 0.000101325; control->P[1] = 0.000101325; control->P[2] = 0.000101325; control->Tau_P[0] = 500.0; control->Tau_P[1] = 500.0; control->Tau_P[2] = 500.0; control->Tau_PT[0] = 500.0; control->Tau_PT[1] = 500.0; control->Tau_PT[2] = 500.0; control->compressibility = 1.0; control->press_mode = 0; out_control->write_steps = 0; out_control->traj_compress = 0; out_control->traj_method = REG_TRAJ; strncpy( out_control->traj_title, "default_title", sizeof(out_control->traj_title) - 1 ); out_control->traj_title[sizeof(out_control->traj_title) - 1] = '\0'; out_control->atom_info = 0; out_control->bond_info = 0; out_control->angle_info = 0; control->molecular_analysis = 0; control->dipole_anal = 0; control->freq_dipole_anal = 0; control->diffusion_coef = 0; control->freq_diffusion_coef = 0; control->restrict_type = 0; /* memory allocations */ s = (char*) smalloc( sizeof(char) * MAX_LINE, "Read_Control_File::s" ); tmp = (char**) smalloc( sizeof(char*) * MAX_TOKENS, "Read_Control_File::tmp" ); for ( i = 0; i < MAX_TOKENS; i++ ) { tmp[i] = (char*) smalloc( sizeof(char) * MAX_LINE, "Read_Control_File::tmp[i]" ); } /* read control parameters file */ while ( fgets( s, MAX_LINE, fp ) ) { c = Tokenize( s, &tmp, MAX_LINE ); if ( c > 0 ) { if ( strncmp(tmp[0], "simulation_name", MAX_LINE) == 0 ) { strncpy( control->sim_name, tmp[1], sizeof(control->sim_name) - 1 ); control->sim_name[sizeof(control->sim_name) - 1] = '\0'; } else if ( strncmp(tmp[0], "ensemble_type", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->ensemble = ival; } else if ( strncmp(tmp[0], "nsteps", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->nsteps = ival; } else if ( strncmp(tmp[0], "dt", MAX_LINE) == 0) { val = atof(tmp[1]); control->dt = val * 1.e-3; // convert dt from fs to ps! } else if ( strncmp(tmp[0], "gpus_per_node", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->gpus_per_node = ival; } else if ( strncmp(tmp[0], "proc_by_dim", MAX_LINE) == 0 ) { if ( c < 4 ) { fprintf( stderr, "[ERROR] invalid number of control file parameters (procs_by_dim). terminating!\n" ); MPI_Abort( MPI_COMM_WORLD, INVALID_INPUT ); } ival = atoi(tmp[1]); control->procs_by_dim[0] = ival; ival = atoi(tmp[2]); control->procs_by_dim[1] = ival; ival = atoi(tmp[3]); control->procs_by_dim[2] = ival; control->nprocs = control->procs_by_dim[0] * control->procs_by_dim[1] * control->procs_by_dim[2]; } else if ( strncmp(tmp[0], "periodic_boundaries", MAX_LINE) == 0 ) { // skip since not supported in distributed memory code ; } // else if( strncmp(tmp[0], "restart", MAX_LINE) == 0 ) // { // ival = atoi(tmp[1]); // control->restart = ival; // } // else if( strncmp(tmp[0], "restart_from", MAX_LINE) == 0 ) // { // strncpy( control->restart_from, tmp[1], sizeof(control->restart_from) - 1 ); // control->restart_from[sizeof(control->restart_from) - 1] = '\0'; // } else if ( strncmp(tmp[0], "random_vel", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->random_vel = ival; } else if ( strncmp(tmp[0], "restart_format", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->restart_format = ival; } else if ( strncmp(tmp[0], "restart_freq", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->restart_freq = ival; } else if ( strncmp(tmp[0], "reposition_atoms", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->reposition_atoms = ival; } else if ( strncmp(tmp[0], "restrict_bonds", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->restrict_bonds = ival; } else if ( strncmp(tmp[0], "remove_CoM_vel", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->remove_CoM_vel = ival; } else if ( strncmp(tmp[0], "debug_level", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->debug_level = ival; } else if ( strncmp(tmp[0], "energy_update_freq", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->energy_update_freq = ival; } else if ( strncmp(tmp[0], "reneighbor", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->reneighbor = ival; } else if ( strncmp(tmp[0], "vlist_buffer", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->vlist_cut = val + control->nonb_cut; } else if ( strncmp(tmp[0], "nbrhood_cutoff", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->bond_cut = val; } else if ( strncmp(tmp[0], "bond_graph_cutoff", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->bg_cut = val; } else if ( strncmp(tmp[0], "thb_cutoff", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->thb_cut = val; } else if ( strncmp(tmp[0], "hbond_cutoff", MAX_LINE) == 0 ) { val = atof( tmp[1] ); control->hbond_cut = val; } else if ( strncmp(tmp[0], "ghost_cutoff", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->user_ghost_cut = val; } else if ( strncmp(tmp[0], "tabulate_long_range", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->tabulate = ival; } else if ( strncmp(tmp[0], "charge_method", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->charge_method = ival; } else if ( strncmp(tmp[0], "charge_freq", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->charge_freq = ival; } else if ( strncmp(tmp[0], "cm_q_net", MAX_LINE) == 0 ) { val = atof( tmp[1] ); control->cm_q_net = val; } else if ( strncmp(tmp[0], "cm_solver_type", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_solver_type = ival; } else if ( strncmp(tmp[0], "cm_solver_max_iters", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_solver_max_iters = ival; } else if ( strncmp(tmp[0], "cm_solver_restart", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_solver_restart = ival; } else if ( strncmp(tmp[0], "cm_solver_q_err", MAX_LINE) == 0 ) { val = atof( tmp[1] ); control->cm_solver_q_err = val; } else if ( strncmp(tmp[0], "cm_domain_sparsity", MAX_LINE) == 0 ) { val = atof( tmp[1] ); control->cm_domain_sparsity = val; if ( val < 1.0 ) { control->cm_domain_sparsify_enabled = TRUE; } } else if ( strncmp(tmp[0], "cm_init_guess_extrap1", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_init_guess_extrap1 = ival; } else if ( strncmp(tmp[0], "cm_init_guess_extrap2", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_init_guess_extrap2 = ival; } else if ( strncmp(tmp[0], "cm_solver_pre_comp_type", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_solver_pre_comp_type = ival; } else if ( strncmp(tmp[0], "cm_solver_pre_comp_refactor", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_solver_pre_comp_refactor = ival; } else if ( strncmp(tmp[0], "cm_solver_pre_comp_droptol", MAX_LINE) == 0 ) { val = atof( tmp[1] ); control->cm_solver_pre_comp_droptol = val; } else if ( strncmp(tmp[0], "cm_solver_pre_comp_sweeps", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_solver_pre_comp_sweeps = ival; } else if ( strncmp(tmp[0], "cm_solver_pre_comp_sai_thres", MAX_LINE) == 0 ) { val = atof( tmp[1] ); control->cm_solver_pre_comp_sai_thres = val; } else if ( strncmp(tmp[0], "cm_solver_pre_app_type", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_solver_pre_app_type = ival; } else if ( strncmp(tmp[0], "cm_solver_pre_app_jacobi_iters", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->cm_solver_pre_app_jacobi_iters = ival; } else if ( strncmp(tmp[0], "include_polarization_energy", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->polarization_energy_enabled = ival; } else if ( strncmp(tmp[0], "temp_init", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->T_init = val; if ( control->T_init < 0.001 ) { control->T_init = 0.001; } } else if ( strncmp(tmp[0], "temp_final", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->T_final = val; if ( control->T_final < 0.1 ) { control->T_final = 0.1; } } else if ( strncmp(tmp[0], "t_mass", MAX_LINE) == 0 ) { val = atof(tmp[1]); /* convert from fs to s */ control->Tau_T = val * 1.0e-15; } else if ( strncmp(tmp[0], "t_mode", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->T_mode = ival; } else if ( strncmp(tmp[0], "t_rate", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->T_rate = val; } else if ( strncmp(tmp[0], "t_freq", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->T_freq = val; } else if ( strncmp(tmp[0], "pressure", MAX_LINE) == 0 ) { if ( control->ensemble == iNPT ) { control->P[0] = control->P[1] = control->P[2] = atof(tmp[1]); } else if ( control->ensemble == sNPT ) { control->P[0] = atof(tmp[1]); control->P[1] = atof(tmp[2]); control->P[2] = atof(tmp[3]); } } else if ( strncmp(tmp[0], "p_mass", MAX_LINE) == 0 ) { // convert p_mass from fs to ps if ( control->ensemble == iNPT ) { control->Tau_P[0] = control->Tau_P[1] = control->Tau_P[2] = atof(tmp[1]) * 1.e-3; } else if ( control->ensemble == sNPT ) { control->Tau_P[0] = atof(tmp[1]) * 1.e-3; control->Tau_P[1] = atof(tmp[2]) * 1.e-3; control->Tau_P[2] = atof(tmp[3]) * 1.e-3; } } else if ( strncmp(tmp[0], "pt_mass", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->Tau_PT[0] = control->Tau_PT[1] = control->Tau_PT[2] = val * 1.e-3; // convert pt_mass from fs to ps } else if ( strncmp(tmp[0], "compress", MAX_LINE) == 0 ) { val = atof(tmp[1]); control->compressibility = val; } else if ( strncmp(tmp[0], "press_mode", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->press_mode = ival; } else if ( strncmp(tmp[0], "geo_format", MAX_LINE) == 0 ) { ival = atoi( tmp[1] ); control->geo_format = ival; } else if ( strncmp(tmp[0], "write_freq", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->write_steps = ival; } else if ( strncmp(tmp[0], "traj_compress", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->traj_compress = ival; } else if ( strncmp(tmp[0], "traj_format", MAX_LINE) == 0 ) { // skip since not applicable to distributed memory code ; } else if ( strncmp(tmp[0], "traj_method", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->traj_method = ival; } else if ( strncmp(tmp[0], "traj_title", MAX_LINE) == 0 ) { strncpy( out_control->traj_title, tmp[1], sizeof(out_control->traj_title) - 1 ); out_control->traj_title[sizeof(out_control->traj_title) - 1] = '\0'; } else if ( strncmp(tmp[0], "atom_info", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->atom_info += ival * 4; } else if ( strncmp(tmp[0], "atom_velocities", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->atom_info += ival * 2; } else if ( strncmp(tmp[0], "atom_forces", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->atom_info += ival * 1; } else if ( strncmp(tmp[0], "bond_info", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->bond_info = ival; } else if ( strncmp(tmp[0], "angle_info", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); out_control->angle_info = ival; } else if ( strncmp(tmp[0], "test_forces", MAX_LINE) == 0 ) { // skip since not supported in distributed memory code ; } else if ( strncmp(tmp[0], "molecular_analysis", MAX_LINE) == 0 || strncmp(tmp[0], "molec_anal", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->molecular_analysis = ival; } else if ( strncmp(tmp[0], "ignore", MAX_LINE) == 0 ) { control->num_ignored = atoi(tmp[1]); for ( i = 0; i < control->num_ignored; ++i ) { control->ignore[atoi(tmp[i + 2])] = 1; } } else if ( strncmp(tmp[0], "freq_molec_anal", MAX_LINE) == 0 ) { // skip since not supported in distributed memory code ; } else if ( strncmp(tmp[0], "dipole_anal", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->dipole_anal = ival; } else if ( strncmp(tmp[0], "freq_dipole_anal", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->freq_dipole_anal = ival; } else if ( strncmp(tmp[0], "diffusion_coef", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->diffusion_coef = ival; } else if ( strncmp(tmp[0], "freq_diffusion_coef", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->freq_diffusion_coef = ival; } else if ( strncmp(tmp[0], "restrict_type", MAX_LINE) == 0 ) { ival = atoi(tmp[1]); control->restrict_type = ival; } else { fprintf( stderr, "[ERROR] unknown control file parameter (%s)\n", tmp[0] ); MPI_Abort( MPI_COMM_WORLD, INVALID_INPUT ); } } } if ( ferror( fp ) ) { fprintf( stderr, "[ERROR] parsing control file failed (I/O error). TERMINATING...\n" ); MPI_Abort( MPI_COMM_WORLD, INVALID_INPUT ); } /* determine target T */ if ( control->T_mode == 0 ) { control->T = control->T_final; } else { control->T = control->T_init; } /* free memory allocations at the top */ for ( i = 0; i < MAX_TOKENS; i++ ) { sfree( tmp[i], "Read_Control_File::tmp[i]" ); } sfree( tmp, "Read_Control_File::tmp" ); sfree( s, "Read_Control_File::s" ); sfclose( fp, "Read_Control_Field::fp" ); }