def basic_test_suite(): """ Simple testing of various functions in the script.""" print "read_lammps_data_file" lattice, type_list = lmp_io.read_lammps_data_file("CG_first_interaction.lammps05") print "read_lammps_rdf" rdf_average = lmp_io.read_lammps_rdf("tmp.1.rdf", 3, 1) print "read_CG_log_file" final_pressure = read_CG_log_file("new_CG.prod1.log") print "smooth_data" smoothed = dm.smooth_data(rdf_average[1][1]) print "read_in_rdf_file" rdf_array, numofbins, cutoff = read_in_rdf_file("rdf", 3, [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]) print "read_in_interaction_files" distance, potential, derivative, pot_file_list, cutoff = lmp_io.read_in_interaction_files("./pot", 3, [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]], 1)
def basic_test_suite(): """ Simple testing of various functions in the script.""" print "read_lammps_data_file" lattice, type_list = lmp_io.read_lammps_data_file( "CG_first_interaction.lammps05") print "read_lammps_rdf" rdf_average = lmp_io.read_lammps_rdf("tmp.1.rdf", 3, 1) print "read_CG_log_file" final_pressure = read_CG_log_file("new_CG.prod1.log") print "smooth_data" smoothed = dm.smooth_data(rdf_average[1][1]) print "read_in_rdf_file" rdf_array, numofbins, cutoff = read_in_rdf_file( "rdf", 3, [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]) print "read_in_interaction_files" distance, potential, derivative, pot_file_list, cutoff = lmp_io.read_in_interaction_files( "./pot", 3, [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]], 1)
def production(): """ This script will create the next interation of coarse-grained potentials using the Iterative Boltzmann Inversion to match to a user-supplied radial distribution function (normally from atomistic simulation). It will also attempt a correction for the pressure. The script will also extrapolate the potentials at low distance values by fitting to a soft Lennard-Jones potential. Note, this fitting is somewhat unstable (CurveFit.pm) and can cause the IBI to fail. """ print "ARGUMENTS TO THE IBI ARE: ", sys.argv # user-supplied arguments to the IBI. Note, not all of these arguments are required depending on what analysis is need and files are provided. lammps_input_file = "" # LAMMPS input file for the current CG iteration. correct_rdf_base = "" # User-supplied Radial Distribution Function to match to (normally derived from atomistic simulation) - distance is column 1 and the RDF is column 3. potential_base = "" # the file base-name for the potential energy files. The format is such: pot.<iteration_number>.new.<type1><type2>. In this case the base-name is "pot". number = 0 # the current IBI iteration number lammps_data_file = "" # LAMMPS CG data file lammps_rdf_file = "" # the CG RDF file if calculated by LAMMPS - this is a series of snapshot values, which need to be averaged. p_target = 1.0 # pressure target for the CG simulation. p_flag = 0.0 # flag to indicate whether to apply pressure correction - set to one if a pressure target is set by the user. CG_output_file = "" # LAMMPS thermodynamic log file for the current CG simulation. Used to calculate the current average CG pressure. p_now = 0 # current CG pressure read from (and averaged) the CG lammps thermodynamic log file; temperature = 300 # temperature the simulations are run at; default is 300K LJ_file_flag = 0 # if this flag is set to one, the parameters used in the extrapolation by fitting to a Lennard-Jones potential are read from a file (called LJ_parameters) rather than computed from fitting to the potential / forces. num_of_bins = 0 DeltaR = 0.0 number_of_arguments = len(sys.argv) mode = "default" num_of_types = 0 for i in xrange(0, number_of_arguments): if sys.argv[i].lower() == "lammps_input_file": lammps_input_file = sys.argv[i+1] print "THE LAMMPS INPUT FILE IS ", lammps_input_file elif sys.argv[i].lower() == "lammps_output_file": lammps_output_file = sys.argv[i+1] print "THE LAMMPS OUTPUT FILE IS ", lammps_input_file elif sys.argv[i].lower() == "lammps_data_file": lammps_data_file = sys.argv[i+1] print "THE LAMMPS DATA FILE IS ", lammps_data_file elif ((sys.argv[i] == "potential_base") or (sys.argv[i] == "potential")): potential_base = sys.argv[i+1] elif sys.argv[i].lower() == "lammps_rdf_file": lammps_rdf_file = sys.argv[i+1] print "THE RDFS WILL BE READ FROM LAMMPS OUTPUT", lammps_rdf_file elif (sys.argv[i] == "correct_rdf_base"): correct_rdf_base = sys.argv[i+1] print "THE RDFS TO MATCH TO HAVE THE FILE BASE ", correct_rdf_base elif ((sys.argv[i] == "number") or (sys.argv[i] == "current_number") or (sys.argv[i] == "iteration_number")): number = int(sys.argv[i+1]) print "THE CURRENT ITERATION NUMBER IS ", number elif ((sys.argv[i] == "pressure_flag") or (sys.argv[i] == "p_flag")): p_flag = float(sys.argv[i+1]) print "THE PRESSURE FLAG is ", p_flag elif ((sys.argv[i] == "pressure_target") or (sys.argv[i] == "p_target")): p_target = float(sys.argv[i+1]) if abs(p_flag) < 0.00001: p_flag = 1 print "THE PRESSURE TARGET is ", p_target elif ((sys.argv[i] == "CG_log_file") or (sys.argv[i] == "CG_logfile")): CG_output_file = sys.argv[i+1] p_now = read_CG_log_file(CG_output_file, label="Press") #TODO: this is only a temp hack! print "THE CURRENT PRESSURE WILL BE CALCULATED FROM THE LOG FILE ", CG_output_file , p_now elif (sys.argv[i] == "temperature"): temperature = float(sys.argv[i+1]) elif (sys.argv[i] == "LJ_param_file"): LJ_file_flag = 1 elif sys.argv[i].lower() == "numofbins": num_of_bins = int(sys.argv[i+1]) print "THE NUMBER OF BINS IS ", num_of_bins elif sys.argv[i].lower() == "deltar": DeltaR = float(sys.argv[i+1]) print "DeltaR IS ", DeltaR elif sys.argv[i] == "mode": mode = sys.argv[i+1] elif sys.argv[i].lower() == "numoftypes": num_of_types = int(sys.argv[i+1]) # read in the lammps data file to identify the number of CG types and lattice parameters. lattice, type_list = lmp_io.read_lammps_data_file(lammps_data_file) num_of_types = len(type_list) print "Num of types = ", num_of_types #num_of_types = 4 number_of_types_array = np.zeros((num_of_types+1)) for n in xrange(1, num_of_types+1): number_of_types_array[n] = len(type_list["%s" % n]) if mode=="pressure_correct": num_of_bins, cutoff, offset = lmp_io.get_number_of_bins_and_cutoff(potential_base, 1) print "Potential numofbins and cutoff:", num_of_bins, cutoff pots = (potential_base.strip()).split('.') atom1 = int(pots[-2]) atom2 = int(pots[-1]) print "ATOMS are:", atom1, atom2 potential = np.zeros((num_of_bins+1)) volume = float(lattice[0]) * float(lattice[1]) * float(lattice[2]) hist_rdf = lmp_io.read_lammps_rdf(lammps_rdf_file, num_of_types, number) pressure_pot = calc_pressure_correction(hist_rdf[atom1][atom2], num_of_bins, DeltaR, number_of_types_array[atom1], number_of_types_array[atom2], abs(p_flag), p_now, p_target, volume, temperature) old_distance, old_potential, old_derivative = lmp_io.read_in_interaction_file(potential_base, num_of_bins) potential = apply_pressure_correction(old_potential, pressure_pot, num_of_bins+1, old_distance[1], DeltaR) potential[0]=potential[1] # TODO: change this temporary workaround into something more systematic. The workaround reduces anomalies in the derivative at the start of the potential. new_derivatives = da.derivatives(np.arange(offset, cutoff, DeltaR), potential) print "dy lens:", num_of_bins, len(new_derivatives), len(np.arange(offset-DeltaR, cutoff, DeltaR)), len(potential) write_pot_file("%s/pot.%d.new.%d.%d" % (os.path.dirname(lammps_output_file), number+1, atom1, atom2), new_derivatives[1:] , potential[1:], num_of_bins, DeltaR, atom1, atom2, num_of_bins, offset, smoothing="no", selection="no") #note: we use an offset here! elif mode=="default": # Either read an interaction list from a file in the atom_dir (useful if you want to parametrize only a subset of interactions), or generate one on the fly. interaction_filename = os.path.dirname(correct_rdf_base) + "/interaction_list" if os.path.exists(interaction_filename): interaction_list = interaction_list_from_file(interaction_filename) else: interaction_list = generate_interaction_list(num_of_types) first_array, num_of_bins, cutoff2 = read_in_rdf_file(correct_rdf_base, num_of_types, interaction_list) # read in the rdfs to match to. print "THE CUTOFF in the RDF files is", cutoff2, ", with", len(first_array[1][1])-1, "number of bins "; print "THIS IS ITERATION NUMBER", number deltaR = cutoff2 / num_of_bins # bin spacing from the RDF previous_position, previous_potential, previous_derivative, old_pot_files, cutoff = lmp_io.read_in_interaction_files(potential_base, num_of_types, interaction_list, number) num_of_bins = int(cutoff / deltaR) print deltaR, cutoff2, num_of_bins, correct_rdf_base print "THE CUTOFF in the POS FILES is", cutoff, "and number of bins are", num_of_bins # read in the RDFs of the CG calculated by LAMMPS. hist_rdf = lmp_io.read_lammps_rdf(lammps_rdf_file, num_of_types, number) # print lammps_rdf_file, len(hist_rdf[1][1]) DeltaR = cutoff / num_of_bins # calculate the IBI compute_update(os.path.dirname(lammps_output_file), first_array, hist_rdf, previous_position, previous_potential, num_of_types, number, DeltaR, num_of_bins, number_of_types_array, lattice, LJ_file_flag, p_flag, p_now, p_target, temperature, interaction_list) # modify the lammps input file, ready for the next iteration modify_lammps_in_file(lammps_input_file, lammps_output_file, number, interaction_list, num_of_types) else: print "ERROR: mode is incorrectly set in IBI.py. Should be e.g., default or pressure_correct" sys.exit()
def production(): """ This script will create the next interation of coarse-grained potentials using the Iterative Boltzmann Inversion to match to a user-supplied radial distribution function (normally from atomistic simulation). It will also attempt a correction for the pressure. The script will also extrapolate the potentials at low distance values by fitting to a soft Lennard-Jones potential. Note, this fitting is somewhat unstable (CurveFit.pm) and can cause the IBI to fail. """ print "ARGUMENTS TO THE IBI ARE: ", sys.argv # user-supplied arguments to the IBI. Note, not all of these arguments are required depending on what analysis is need and files are provided. lammps_input_file = "" # LAMMPS input file for the current CG iteration. correct_rdf_base = "" # User-supplied Radial Distribution Function to match to (normally derived from atomistic simulation) - distance is column 1 and the RDF is column 3. potential_base = "" # the file base-name for the potential energy files. The format is such: pot.<iteration_number>.new.<type1><type2>. In this case the base-name is "pot". number = 0 # the current IBI iteration number lammps_data_file = "" # LAMMPS CG data file lammps_rdf_file = "" # the CG RDF file if calculated by LAMMPS - this is a series of snapshot values, which need to be averaged. p_target = 1.0 # pressure target for the CG simulation. p_flag = 0.0 # flag to indicate whether to apply pressure correction - set to one if a pressure target is set by the user. CG_output_file = "" # LAMMPS thermodynamic log file for the current CG simulation. Used to calculate the current average CG pressure. p_now = 0 # current CG pressure read from (and averaged) the CG lammps thermodynamic log file; temperature = 300 # temperature the simulations are run at; default is 300K LJ_file_flag = 0 # if this flag is set to one, the parameters used in the extrapolation by fitting to a Lennard-Jones potential are read from a file (called LJ_parameters) rather than computed from fitting to the potential / forces. num_of_bins = 0 DeltaR = 0.0 number_of_arguments = len(sys.argv) mode = "default" num_of_types = 0 for i in xrange(0, number_of_arguments): if sys.argv[i].lower() == "lammps_input_file": lammps_input_file = sys.argv[i + 1] print "THE LAMMPS INPUT FILE IS ", lammps_input_file elif sys.argv[i].lower() == "lammps_output_file": lammps_output_file = sys.argv[i + 1] print "THE LAMMPS OUTPUT FILE IS ", lammps_input_file elif sys.argv[i].lower() == "lammps_data_file": lammps_data_file = sys.argv[i + 1] print "THE LAMMPS DATA FILE IS ", lammps_data_file elif ((sys.argv[i] == "potential_base") or (sys.argv[i] == "potential")): potential_base = sys.argv[i + 1] elif sys.argv[i].lower() == "lammps_rdf_file": lammps_rdf_file = sys.argv[i + 1] print "THE RDFS WILL BE READ FROM LAMMPS OUTPUT", lammps_rdf_file elif (sys.argv[i] == "correct_rdf_base"): correct_rdf_base = sys.argv[i + 1] print "THE RDFS TO MATCH TO HAVE THE FILE BASE ", correct_rdf_base elif ((sys.argv[i] == "number") or (sys.argv[i] == "current_number") or (sys.argv[i] == "iteration_number")): number = int(sys.argv[i + 1]) print "THE CURRENT ITERATION NUMBER IS ", number elif ((sys.argv[i] == "pressure_flag") or (sys.argv[i] == "p_flag")): p_flag = float(sys.argv[i + 1]) print "THE PRESSURE FLAG is ", p_flag elif ((sys.argv[i] == "pressure_target") or (sys.argv[i] == "p_target")): p_target = float(sys.argv[i + 1]) if abs(p_flag) < 0.00001: p_flag = 1 print "THE PRESSURE TARGET is ", p_target elif ((sys.argv[i] == "CG_log_file") or (sys.argv[i] == "CG_logfile")): CG_output_file = sys.argv[i + 1] p_now = read_CG_log_file(CG_output_file, label="Press") #TODO: this is only a temp hack! print "THE CURRENT PRESSURE WILL BE CALCULATED FROM THE LOG FILE ", CG_output_file, p_now elif (sys.argv[i] == "temperature"): temperature = float(sys.argv[i + 1]) elif (sys.argv[i] == "LJ_param_file"): LJ_file_flag = 1 elif sys.argv[i].lower() == "numofbins": num_of_bins = int(sys.argv[i + 1]) print "THE NUMBER OF BINS IS ", num_of_bins elif sys.argv[i].lower() == "deltar": DeltaR = float(sys.argv[i + 1]) print "DeltaR IS ", DeltaR elif sys.argv[i] == "mode": mode = sys.argv[i + 1] elif sys.argv[i].lower() == "numoftypes": num_of_types = int(sys.argv[i + 1]) # read in the lammps data file to identify the number of CG types and lattice parameters. lattice, type_list = lmp_io.read_lammps_data_file(lammps_data_file) num_of_types = len(type_list) print "Num of types = ", num_of_types #num_of_types = 4 number_of_types_array = np.zeros((num_of_types + 1)) for n in xrange(1, num_of_types + 1): number_of_types_array[n] = len(type_list["%s" % n]) if mode == "pressure_correct": num_of_bins, cutoff, offset = lmp_io.get_number_of_bins_and_cutoff( potential_base, 1) print "Potential numofbins and cutoff:", num_of_bins, cutoff pots = (potential_base.strip()).split('.') atom1 = int(pots[-2]) atom2 = int(pots[-1]) print "ATOMS are:", atom1, atom2 potential = np.zeros((num_of_bins + 1)) volume = float(lattice[0]) * float(lattice[1]) * float(lattice[2]) hist_rdf = lmp_io.read_lammps_rdf(lammps_rdf_file, num_of_types, number) pressure_pot = calc_pressure_correction(hist_rdf[atom1][atom2], num_of_bins, DeltaR, number_of_types_array[atom1], number_of_types_array[atom2], abs(p_flag), p_now, p_target, volume, temperature) old_distance, old_potential, old_derivative = lmp_io.read_in_interaction_file( potential_base, num_of_bins) potential = apply_pressure_correction(old_potential, pressure_pot, num_of_bins + 1, old_distance[1], DeltaR) potential[0] = potential[ 1] # TODO: change this temporary workaround into something more systematic. The workaround reduces anomalies in the derivative at the start of the potential. new_derivatives = da.derivatives(np.arange(offset, cutoff, DeltaR), potential) print "dy lens:", num_of_bins, len(new_derivatives), len( np.arange(offset - DeltaR, cutoff, DeltaR)), len(potential) write_pot_file( "%s/pot.%d.new.%d.%d" % (os.path.dirname(lammps_output_file), number + 1, atom1, atom2), new_derivatives[1:], potential[1:], num_of_bins, DeltaR, atom1, atom2, num_of_bins, offset, smoothing="no", selection="no") #note: we use an offset here! elif mode == "default": # Either read an interaction list from a file in the atom_dir (useful if you want to parametrize only a subset of interactions), or generate one on the fly. interaction_filename = os.path.dirname( correct_rdf_base) + "/interaction_list" if os.path.exists(interaction_filename): interaction_list = interaction_list_from_file(interaction_filename) else: interaction_list = generate_interaction_list(num_of_types) first_array, num_of_bins, cutoff2 = read_in_rdf_file( correct_rdf_base, num_of_types, interaction_list) # read in the rdfs to match to. print "THE CUTOFF in the RDF files is", cutoff2, ", with", len( first_array[1][1]) - 1, "number of bins " print "THIS IS ITERATION NUMBER", number deltaR = cutoff2 / num_of_bins # bin spacing from the RDF previous_position, previous_potential, previous_derivative, old_pot_files, cutoff = lmp_io.read_in_interaction_files( potential_base, num_of_types, interaction_list, number) num_of_bins = int(cutoff / deltaR) print deltaR, cutoff2, num_of_bins, correct_rdf_base print "THE CUTOFF in the POS FILES is", cutoff, "and number of bins are", num_of_bins # read in the RDFs of the CG calculated by LAMMPS. hist_rdf = lmp_io.read_lammps_rdf(lammps_rdf_file, num_of_types, number) # print lammps_rdf_file, len(hist_rdf[1][1]) DeltaR = cutoff / num_of_bins # calculate the IBI compute_update(os.path.dirname(lammps_output_file), first_array, hist_rdf, previous_position, previous_potential, num_of_types, number, DeltaR, num_of_bins, number_of_types_array, lattice, LJ_file_flag, p_flag, p_now, p_target, temperature, interaction_list) # modify the lammps input file, ready for the next iteration modify_lammps_in_file(lammps_input_file, lammps_output_file, number, interaction_list, num_of_types) else: print "ERROR: mode is incorrectly set in IBI.py. Should be e.g., default or pressure_correct" sys.exit()