def load_pickle_data(old_pickle_file, directory): try: pickle_data = hf.load_pickle(old_pickle_file) except SyntaxError: # This pickle is from a python 2 version of MorphCT. We can inject # a line into the obtainChromophores.py to try and fix the import # error print( "Pickle is from Python 2, updating the code so it can be imported..." ) code_file_names = ["obtainChromophores.py", "helperFunctions.py"] for code_file_name in code_file_names: print("Updating", "".join([code_file_name, "..."])) with open(os.path.join(directory, code_file_name), "r") as code_file: code_lines = code_file.readlines() for line_number, line in enumerate(code_lines): if "import cPickle as pickle" in line: code_lines[line_number] = "import pickle\n" elif ("#" not in line) and ("print" in line): n_spaces = len(line) - len(line.lstrip()) code_lines[line_number] = "".join( [" " * n_spaces, "print()\n"]) with open(os.path.join(directory, code_file_name), "w+") as code_file: code_file.writelines(code_lines) pickle_data = hf.load_pickle(old_pickle_file) return pickle_data
def test_pickles(self): # First load the test file input_file = os.path.join(TEST_ROOT, "assets", "hf_test.pickle") data = hf.load_pickle(input_file) assert len(data) == 5, ( "Expected pickle file to contain 5 elements, instead it" + " contained " + repr(len(data)) + ".") assert type(data[0]) == dict, ( "Expected first element of the pickle file (AA_morphology_dict)" + " to be a dictionary, instead its type is " + repr(type(data[0])) + ".") assert type(data[1]) == dict, ( "Expected second element of the pickle file (CG_morphology_dict)" + " to be a dictionary, instead its type is " + repr(type(data[1])) + ".") assert type(data[2]) == list, ( "Expected third element of the pickle file (CG_to_AAID_master)" + " to be a list, instead its type is " + repr(type(data[2])) + ".") assert type(data[3]) == dict, ( "Expected fourth element of the pickle file (parameter_dict)" + " to be a dictionary, instead its type is " + repr(type(data[3])) + ".") assert type(data[4]) == list, ( "Expected fifth element of the pickle file (chromophore_list)" + " to be a list, instead its type is " + repr(type(data[4])) + ".") # Then write it out somewhere else output_file = os.path.join(TEST_ROOT, "output_hf", "test_output.pickle") self.confirm_file_exists(output_file, function="write_pickle", posn_args=[data, output_file])
def __init__(self, mol_morph_name, parameter_dict): chromophore_list_location = os.path.join( parameter_dict["output_morph_dir"], mol_morph_name, "code", "".join([mol_morph_name, ".pickle"]), ) pickle_data = hf.load_pickle(chromophore_list_location) self.AA_morphology_dict = pickle_data[0] self.parameter_dict = pickle_data[3] self.chromophore_list = pickle_data[4] self.carrier_type = self.get_carrier_type() # Now add the occupation data to the chromophoreLists so that we can # prevent double occupation in the simulations. # The occupied property is a list that contains the device moiety # coordinates where the chromophore is occupied. for index, chromophore in enumerate(self.chromophore_list): chromophore.occupied = []
return [ AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list, ] if __name__ == "__main__": try: pickle_file = sys.argv[1] except: print( "Please specify the pickle file to load to continue the pipeline from this" " point." ) pickle_data = hf.load_pickle(pickle_file) AA_morphology_dict = pickle_data[0] CG_morphology_dict = pickle_data[1] CG_to_AAID_master = pickle_data[2] parameter_dict = pickle_data[3] chromophore_list = pickle_data[4] main( AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list, )
def manual_load(table, infile, C1_index, C2_index): """ A manual way to load in the data when we only want to compare a pair of chromophores. Requires: table - string, the name of the table in the database infile - string, the name of the pickle file C1_index - integer for chromophore 1 C2_index - integer for chromophore 2 """ AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list = hf.load_pickle(infile) box = np.array([[AA_morphology_dict['lx'], AA_morphology_dict['ly'], AA_morphology_dict['lz']]]) write_positions_to_xyz(C1_index, C2_index, chromophore_list, AA_morphology_dict, box)
def run_system(table, infile, molecule_dict, species, mers=15): """ Calculate the relative orientational data for pairs of chromophores. Requires: table - string, the name of the table in the database infile - string, the name of the pickle file molecule_dict - dictionary containing molecule information species - string, 'donor' or 'acceptor' """ #Load in the data AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list = hf.load_pickle(infile) #Get the number of the desired species for creating the dictionary species_list = [chromophore.species for chromophore in chromophore_list] chromo_IDs = [index for index, chromo_species in enumerate(species_list) if chromo_species == species] vector_dict = generate_empty_dict(chromo_IDs) #Set up the periodic simulation box into a single variable. box = np.array([[AA_morphology_dict['lx'], AA_morphology_dict['ly'], AA_morphology_dict['lz']]]) vector_dict = fill_dict(vector_dict, chromophore_list, AA_morphology_dict, box, species, molecule_dict['atom_indices']) data = [] # List for storing the calculated data molecule_list = identify_chains(AA_morphology_dict, chromophore_list) sulfur_distances = [] #Because DBP has fullerenes, iterate only up to #where the system is DBP #Iterate through all the chromophores. print("Extracting descriptors from all chromophores...") for i, chromophore in enumerate(chromophore_list): #Only get the desired acceptor or donor index, needed for blends. if chromophore.species == species: #Iterate through the neighbors of each chromophore. for neighbor in zip(chromophore.neighbours, chromophore.neighbours_delta_E, chromophore.neighbours_TI): index1 = i index2 = neighbor[0][0] # Gets the neighbor's index relative_image = neighbor[0][1] # Gets the neighbour's image dE = neighbor[1] # Get the difference in energy TI = neighbor[2] # Get the transfer integral same_chain = check_same_chain(molecule_list, index1, index2, mers) if os.path.splitext(molecule_dict['database'])[0].lower() == 'p3ht': sulfur_distance = get_sulfur_separation(chromophore, chromophore_list[index2], relative_image, box[0], AA_morphology_dict) else: sulfur_distance = 0 if (TI is None) or (TI > 0): # Consider only pairs that will have hops. #Get the location of the other chromophore and make sure they're in the #same periodic image. index2_loc = check_vector(chromophore_list[index2].posn, chromophore.posn, box) #Calculate the distance (normally this is in Angstroms) centers_vec = chromophore.posn - index2_loc #Get the vectors describing the two chromophores vdict1 = vector_dict[index1] vdict2 = vector_dict[index2] #Calculate the differences in alignment between the chromophores # Vec1 for DBP is (midpoint(1, 2) -> 3) (along Y axis) # Vec2 for DBP is (1 -> 2) (along X axis) # Vec3 for DBP is Normal to both (along Z axis) # MJ note: FOR DBP ONLY if we assume the chromophore is identical above # and below the plane of the molecule, then because # dot(a, b) == - dot(a, -b), we can reduce the dimensionality # of our data further by just taking the absolute value of the # dot product. rotY = np.dot(vdict1['vec1'], vdict2['vec1']) rotX = np.dot(vdict1['vec2'], vdict2['vec2']) rotZ = np.dot(vdict1['vec3'], vdict2['vec3']) # We need to calculate a rotation matrix that can map the normal vector # describing the plane of the first chromophore to the z-axis. # We can define this rotation matrix as the required transformation to # map the normal of chromophore 1 (a) to the unit z axis (b). rotation_matrix = calculate_rotation_matrix(vdict1['vec3'], vdict1['vec2']) old_length = np.linalg.norm(centers_vec) transformed_separation_vec = np.matmul(rotation_matrix, centers_vec) new_length = np.linalg.norm(transformed_separation_vec) assert np.isclose(old_length, new_length) # import matplotlib.pyplot as plt # import mpl_toolkits.mplot3d as p3 # fig = plt.figure() # ax = p3.Axes3D(fig) # plt.plot([0, centers_vec[0]], [0, centers_vec[1]], zs=[0, centers_vec[2]], c='b', label="Original") # plt.plot([0, vdict1['vec3'][0]], [0, vdict1['vec3'][1]], zs=[0, vdict1['vec3'][2]], c='c', label="Orig Vec3") # plt.plot([0, transformed_separation_vec[0]], [0, transformed_separation_vec[1]], zs=[0, transformed_separation_vec[2]], c='r', label="Rotated") # rotated_vec3 = np.matmul(rotation_matrix, vdict1['vec3']) # plt.plot([0, rotated_vec3[0]], [0, rotated_vec3[1]], zs=[0, rotated_vec3[2]], c='m', label="Rotated Vec3") # plt.legend() # plt.show() posX = centers_vec[0] posY = centers_vec[1] posZ = centers_vec[2] #Combine the data into an array datum = np.array([index1, index2, posX, posY, posZ, rotX, rotY, rotZ, dE, same_chain, sulfur_distance, TI]) data.append(datum) #Write the data to the list data = np.array(data) #Turn the list into an array, may be unnecessary add_to_database(table, data, molecule_dict['database']) #Write the data to the database
def main(): global log_file KMC_directory = sys.argv[1] CPU_rank = int(sys.argv[2]) np.random.seed(int(sys.argv[3])) overwrite = False try: overwrite = bool(sys.argv[4]) except: pass # Load `jobs_to_run' which is a list, where each element contains the # [carrier.ID, carrier.lifetime, carrier.carrierType] pickle_file_name = os.path.join(KMC_directory, "KMC_data_{:02d}.pickle".format(CPU_rank)) with open(pickle_file_name, "rb") as pickle_file: jobs_to_run = pickle.load(pickle_file) log_file = os.path.join(KMC_directory, "KMC_log_{:02d}.log".format(CPU_rank)) # Reset the log file with open(log_file, "wb+") as log_file_handle: pass hf.write_to_file(log_file, ["Found {:d} jobs to run".format(len(jobs_to_run))]) # Set the affinities for this current process to make sure it's maximising # available CPU usage current_PID = os.getpid() # try: # affinity_job = sp.Popen(['taskset', '-pc', str(CPU_rank), str(current_PID)], # stdin=sp.PIPE, stdout=sp.PIPE, # stderr=sp.PIPE).communicate() # # hf.write_to_file(log_file, affinity_job[0].split('\n')) # # hf.write_to_file(log_file, affinity_job[1].split('\n')) # except OSError: # hf.write_to_file(log_file, ["Taskset command not found, skipping setting of" # " processor affinity..."]) # Now load the main morphology pickle (used as a workaround to obtain the # chromophore_list without having to save it in each carrier [very memory # inefficient!]) pickle_dir = KMC_directory.replace("/KMC", "/code") for file_name in os.listdir(pickle_dir): if "pickle" in file_name: main_morphology_pickle_name = os.path.join(pickle_dir, file_name) hf.write_to_file( log_file, [ "".join([ "Found main morphology pickle file at ", main_morphology_pickle_name, "! loading data...", ]) ], ) pickle_data = hf.load_pickle(main_morphology_pickle_name) AA_morphology_dict = pickle_data[0] CG_morphology_dict = pickle_data[1] CG_to_AAID_master = pickle_data[2] parameter_dict = pickle_data[3] chromophore_list = pickle_data[4] hf.write_to_file(log_file, ["Main morphology pickle loaded!"]) try: if parameter_dict["use_average_hop_rates"] is True: # Chosen to split hopping by inter-intra molecular hops, so get # molecule data mol_ID_dict = split_molecules(AA_morphology_dict) # molIDDict is a dictionary where the keys are the chromoIDs, and # the vals are the molIDs else: raise KeyError except KeyError: mol_ID_dict = None # Attempt to catch a kill signal to ensure that we save the pickle before # termination killer = termination_signal() # Save the pickle as a list of `saveCarrier' instances that contain the # bare minimum save_data = initialise_save_data(len(chromophore_list), int(sys.argv[3])) if parameter_dict["record_carrier_history"] is False: save_data["hole_history_matrix"] = None save_data["electron_history_matrix"] = None t0 = T.time() save_time = T.time() save_slot = "slot1" try: for job_number, [carrier_no, lifetime, carrier_type] in enumerate(jobs_to_run): t1 = T.time() # Find a random position to start the carrier in while True: start_chromo_ID = np.random.randint(0, len(chromophore_list) - 1) if (carrier_type.lower() == "electron") and ( chromophore_list[start_chromo_ID].species.lower() != "acceptor"): continue elif (carrier_type.lower() == "hole") and ( chromophore_list[start_chromo_ID].species.lower() != "donor"): continue break # Create the carrier instance this_carrier = carrier( chromophore_list, parameter_dict, start_chromo_ID, lifetime, carrier_no, AA_morphology_dict, mol_ID_dict, ) terminate_simulation = False while terminate_simulation is False: terminate_simulation = bool( this_carrier.calculate_hop(chromophore_list)) if killer.kill_sent is True: raise terminate( "Kill command sent, terminating KMC simulation...") # Now the carrier has finished hopping, let's calculate its vitals initial_position = this_carrier.initial_chromophore.posn final_position = this_carrier.current_chromophore.posn final_image = this_carrier.image sim_dims = this_carrier.sim_dims this_carrier.displacement = calculate_displacement( initial_position, final_position, final_image, sim_dims) # Now the calculations are completed, create a barebones class # containing the save data importantData = [ "ID", "image", "lifetime", "current_time", "no_hops", "displacement", "carrier_type", ] for name in importantData: save_data[name].append(this_carrier.__dict__[name]) # Update the carrierHistoryMatrix if parameter_dict["record_carrier_history"] is True: if this_carrier.carrier_type.lower() == "hole": save_data[ "hole_history_matrix"] += this_carrier.hole_history_matrix elif this_carrier.carrier_type.lower() == "electron": save_data[ "electron_history_matrix"] += this_carrier.electron_history_matrix # Then add in the initial and final positions save_data["initial_position"].append(initial_position) save_data["final_position"].append(final_position) t2 = T.time() elapsed_time = float(t2) - float(t1) if elapsed_time < 60: time_units = "seconds." elif elapsed_time < 3600: elapsed_time /= 60.0 time_units = "minutes." elif elapsed_time < 86400: elapsed_time /= 3600.0 time_units = "hours." else: elapsed_time /= 86400.0 time_units = "days." hf.write_to_file( log_file, [ "".join([ "{0:s} hopped {1:d} times, over {2:.2e} seconds, into image " .format( this_carrier.carrier_type.capitalize(), this_carrier.no_hops, this_carrier.current_time, ), repr(this_carrier.image), ", for a displacement of {0:.2f}, in {1:.2f} wall-clock {2:s}" .format(this_carrier.displacement, elapsed_time, time_units), ]) ], ) # Save the pickle file every hour if (t2 - save_time) > 3600: print( "Completed {0:d} of {1:d} jobs. Making checkpoint at {2:3d}%%" .format( job_number, len(jobs_to_run), np.round( (job_number + 1) / float(len(jobs_to_run)) * 100), )) hf.write_to_file( log_file, [ "Completed {0:d} of {1:d} jobs. Making checkpoint at {2:3d}%%" .format( job_number, len(jobs_to_run), np.round((job_number + 1) / float(len(jobs_to_run)) * 100), ) ], ) save_pickle( save_data, pickle_file_name.replace("data", "".join([save_slot, "_results"])), ) if save_slot.lower() == "slot1": save_slot = "slot2" elif save_slot.lower() == "slot2": save_slot = "slot1" save_time = T.time() except Exception as error_message: print(traceback.format_exc()) print("Saving the pickle file cleanly before termination...") hf.write_to_file(log_file, [str(error_message)]) hf.write_to_file( log_file, ["Saving the pickle file cleanly before termination..."]) save_pickle(save_data, pickle_file_name.replace("data", "terminated_results")) print("Pickle saved! Exitting Python...") exit() t3 = T.time() elapsed_time = float(t3) - float(t0) if elapsed_time < 60: time_units = "seconds." elif elapsed_time < 3600: elapsed_time /= 60.0 time_units = "minutes." elif elapsed_time < 86400: elapsed_time /= 3600.0 time_units = "hours." else: elapsed_time /= 86400.0 time_units = "days." hf.write_to_file( log_file, [ "All jobs completed in {0:.2f} {1:s}".format( elapsed_time, time_units) ], ) hf.write_to_file(log_file, ["Saving the pickle file cleanly before termination..."]) save_pickle(save_data, pickle_file_name.replace("data", "results")) hf.write_to_file(log_file, ["Exiting normally..."])
def run_simulation(request): _voronoi = request.param["voronoi"] _hop_range_value = request.param["hop_range"] _transiting = request.param["transiting"] _koopmans = request.param["koopmans"] if _hop_range_value != 10.0: _hop_range = True else: _hop_range = False _modifiers = {"True": [], "False": []} for _key in request.param.keys(): _boolean = eval("".join(["_", _key])) _modifiers[repr(_boolean)].append(_key) # ---==============================================--- # ---======== Directory and File Structure ========--- # ---==============================================--- input_morph_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_morph_dir = os.path.join(TEST_ROOT, "output_OC") output_orca_dir = None input_device_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_device_dir = os.path.join(TEST_ROOT, "output_OC") # ---==============================================--- # ---========== Input Morphology Details ==========--- # ---==============================================--- morphology = "donor_polymer.xml" input_sigma = 3.0 device_morphology = None device_components = {} overwrite_current_data = True random_seed_override = 929292929 # ---==============================================--- # ---============= Execution Modules ==============--- # ---==============================================--- execute_fine_graining = False # Requires: None execute_molecular_dynamics = False # Requires: fine_graining execute_obtain_chromophores = ( True) # Requires: Atomistic morphology, or molecular_dynamics execute_ZINDO = False # Requires: obtain_chromophores execute_calculate_transfer_integrals = False # Requires: execute_ZINDO execute_calculate_mobility = False # Requires: calculate_transfer_integrals execute_device_simulation = ( False ) # Requires: calculate_transfer_integrals for all device_components # ---==============================================--- # ---============ Chromophore Parameters ==========--- # ---==============================================--- molecule_terminating_connections = {"C1": [[2, 1]], "C10": [[2, 1]]} AA_rigid_body_species = {} CG_site_species = {"A": "donor", "B": "none", "C": "none"} use_voronoi_neighbours = _voronoi maximum_hole_hop_distance = _hop_range maximum_electron_hop_distance = _hop_range permit_hops_through_opposing_chromophores = _transiting remove_orca_inputs = False remove_orca_outputs = True chromophore_length = 3 # ---==============================================--- # ---=== Chromophore Energy Scaling Parameters ====--- # ---==============================================--- chromophore_species = { "donor": { "literature_MO": -5.0, "target_DOS_std": 0.1, "reorganisation_energy": 0.3064, "species": "donor", "VRH_delocalisation": 2e-10, } } use_koopmans_approximation = _koopmans koopmans_hopping_prefactor = 1E-3 # ---==============================================--- # ---================= Begin run ==================--- # ---==============================================--- parameter_file = os.path.realpath(__file__) proc_IDs = hf.get_CPU_cores() parameter_names = [ i for i in dir() if (not i.startswith("_")) and ( not i.startswith("@")) and (not i.startswith("Test")) and ( not i.startswith("test")) and (i not in [ "run_MorphCT", "helper_functions", "hf", "os", "shutil", "TestCommand", "TEST_ROOT", "setup_module", "teardown_module", "testing_tools", "sys", "pytest", "request", ]) ] parameters = {} for name in parameter_names: parameters[name] = locals()[name] # ---==============================================--- # ---=============== Setup Prereqs ================--- # ---==============================================--- try: shutil.rmtree(output_morph_dir) except OSError: pass os.makedirs( os.path.join(output_morph_dir, os.path.splitext(morphology)[0], "code")) shutil.copy( os.path.join( TEST_ROOT, "assets", os.path.splitext(morphology)[0], "OC", morphology.replace(".xml", "_post_run_HOOMD.pickle"), ), os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), ), ) run_MorphCT.simulation( **parameters) # Execute MorphCT using these simulation parameters # The output dictionary from this fixing fix_dict = {} # Load the output pickle output_pickle_data = hf.load_pickle( os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), )) fix_dict["output_AA_morphology_dict"] = output_pickle_data[0] fix_dict["output_CG_morphology_dict"] = output_pickle_data[1] fix_dict["output_CG_to_AAID_master"] = output_pickle_data[2] fix_dict["output_parameter_dict"] = output_pickle_data[3] fix_dict["output_chromophore_list"] = output_pickle_data[4] # Load the correct expected pickle pickle_name = os.path.join( input_morph_dir, "OC", morphology.replace(".xml", "_post_obtain_chromophores")) pickle_name_modified = "_".join([pickle_name] + sorted(_modifiers["True"])) expected_pickle_data = hf.load_pickle("".join( [pickle_name_modified, ".pickle"])) fix_dict["expected_AA_morphology_dict"] = expected_pickle_data[0] fix_dict["expected_CG_morphology_dict"] = expected_pickle_data[1] fix_dict["expected_CG_to_AAID_master"] = expected_pickle_data[2] fix_dict["expected_parameter_dict"] = expected_pickle_data[3] fix_dict["expected_chromophore_list"] = expected_pickle_data[4] return fix_dict
def run_simulation(): # ---==============================================--- # ---======== Directory and File Structure ========--- # ---==============================================--- input_morph_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_morph_dir = os.path.join(TEST_ROOT, "output_FG") output_orca_dir = None input_device_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_device_dir = os.path.join(TEST_ROOT, "output_FG") # ---==============================================--- # ---========== Input Morphology Details ==========--- # ---==============================================--- morphology = "donor_polymer.xml" input_sigma = 3.0 device_morphology = None device_components = {} overwrite_current_data = True random_seed_override = 929292929 # ---==============================================--- # ---============= Execution Modules ==============--- # ---==============================================--- execute_fine_graining = True # Requires: None execute_molecular_dynamics = False # Requires: fine_graining execute_obtain_chromophores = ( False) # Requires: Atomistic morphology, or molecular_dynamics execute_ZINDO = False # Requires: obtain_chromophores execute_calculate_transfer_integrals = False # Requires: execute_ZINDO execute_calculate_mobility = False # Requires: calculate_transfer_integrals execute_device_simulation = ( False ) # Requires: calculate_transfer_integrals for all device_components # ---==============================================--- # ---========== Fine Graining Parameters ==========--- # ---==============================================--- CG_to_template_dirs = { "A": os.path.join(TEST_ROOT, "assets", "donor_polymer"), "B": os.path.join(TEST_ROOT, "assets", "donor_polymer"), "C": os.path.join(TEST_ROOT, "assets", "donor_polymer"), } CG_to_template_files = { "A": "P3HT_template.xml", "B": "P3HT_template.xml", "C": "P3HT_template.xml", } CG_to_template_force_fields = { "A": "test_FF.xml", "B": "test_FF.xml", "C": "test_FF.xml", } CG_to_template_AAIDs = { "A": [0, 1, 2, 3, 4, 24], "B": [5, 6, 7, 18, 19, 20, 21, 22, 23], "C": [8, 9, 10, 11, 12, 13, 14, 15, 16, 17], } CG_to_template_bonds = {"bondB": ["C2-C3", 2, 5], "bondC": ["C5-C6", 7, 8]} rigid_body_sites = {"A": [0, 1, 2, 3, 4]} additional_constraints = [ ["C1-C10", 3, 25], ["C1-C10-C9", 3, 25, 26], ["C1-C10-S1", 3, 25, 29], ["S1-C1-C10", 4, 3, 25], ["C2-C1-C10", 2, 3, 25], ["C1-C10-C9-C2", 3, 25, 26, 27], ["C1-C10-S1-C1", 3, 25, 29, 28], ["S1-C1-C10-S1", 4, 3, 25, 29], ["C2-C1-C10-S1", 2, 3, 25, 29], ] molecule_terminating_connections = {"C1": [[2, 1]], "C10": [[2, 1]]} # ---==============================================--- # ---================= Begin run ==================--- # ---==============================================--- parameter_file = os.path.realpath(__file__) proc_IDs = hf.get_CPU_cores() parameter_names = [ i for i in dir() if (not i.startswith("__")) and ( not i.startswith("@")) and (not i.startswith("Test")) and ( not i.startswith("test")) and (i not in [ "run_MorphCT", "helper_functions", "hf", "os", "shutil", "TestCommand", "TEST_ROOT", "setup_module", "teardown_module", "testing_tools", "sys", "pytest", ]) ] parameters = {} for name in parameter_names: parameters[name] = locals()[name] run_MorphCT.simulation( **parameters) # Execute MorphCT using these simulation parameters # The output dictionary from this fixing fix_dict = {} # Load the output pickle output_pickle_data = hf.load_pickle( os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), )) fix_dict["output_AA_morphology_dict"] = output_pickle_data[0] fix_dict["output_CG_morphology_dict"] = output_pickle_data[1] fix_dict["output_CG_to_AAID_master"] = output_pickle_data[2] fix_dict["output_parameter_dict"] = output_pickle_data[3] fix_dict["output_chromophore_list"] = output_pickle_data[4] # Load the expected pickle expected_pickle_data = hf.load_pickle( os.path.join( input_morph_dir, "FG", morphology.replace(".xml", "_post_fine_graining.pickle"), )) fix_dict["expected_AA_morphology_dict"] = expected_pickle_data[0] fix_dict["expected_CG_morphology_dict"] = expected_pickle_data[1] fix_dict["expected_CG_to_AAID_master"] = expected_pickle_data[2] fix_dict["expected_parameter_dict"] = expected_pickle_data[3] fix_dict["expected_chromophore_list"] = expected_pickle_data[4] return fix_dict
def run_simulation(): # ---==============================================--- # ---======== Directory and File Structure ========--- # ---==============================================--- input_morph_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_morph_dir = os.path.join(TEST_ROOT, "output_TI") output_orca_dir = None input_device_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_device_dir = os.path.join(TEST_ROOT, "output_TI") # ---==============================================--- # ---========== Input Morphology Details ==========--- # ---==============================================--- morphology = "donor_polymer.xml" input_sigma = 3.0 device_morphology = None device_components = {} overwrite_current_data = True random_seed_override = 929292929 # ---==============================================--- # ---============= Execution Modules ==============--- # ---==============================================--- execute_fine_graining = False # Requires: None execute_molecular_dynamics = False # Requires: fine_graining execute_obtain_chromophores = ( False) # Requires: Atomistic morphology, or molecular_dynamics execute_ZINDO = False # Requires: obtain_chromophores execute_calculate_transfer_integrals = True # Requires: execute_ZINDO execute_calculate_mobility = False # Requires: calculate_transfer_integrals execute_device_simulation = ( False ) # Requires: calculate_transfer_integrals for all device_components remove_orca_inputs = False remove_orca_outputs = False # ---==============================================--- # ---================= Begin run ==================--- # ---==============================================--- parameter_file = os.path.realpath(__file__) proc_IDs = hf.get_CPU_cores() parameter_names = [ i for i in dir() if (not i.startswith("__")) and ( not i.startswith("@")) and (not i.startswith("Test")) and ( not i.startswith("test")) and (i not in [ "run_MorphCT", "helper_functions", "hf", "os", "shutil", "TestCommand", "TEST_ROOT", "setup_module", "teardown_module", "testing_tools", "sys", "pytest", ]) ] parameters = {} for name in parameter_names: parameters[name] = locals()[name] # ---==============================================--- # ---=============== Setup Prereqs ================--- # ---==============================================--- try: shutil.rmtree(output_morph_dir) except OSError: pass os.makedirs( os.path.join(output_morph_dir, os.path.splitext(morphology)[0], "code")) shutil.copy( os.path.join( TEST_ROOT, "assets", os.path.splitext(morphology)[0], "TI", morphology.replace(".xml", "_post_execute_ZINDO.pickle"), ), os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), ), ) shutil.copytree( os.path.join(TEST_ROOT, "assets", os.path.splitext(morphology)[0], "TI", "input_orca"), os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "chromophores", "input_orca", ), ) shutil.copytree( os.path.join(TEST_ROOT, "assets", os.path.splitext(morphology)[0], "TI", "output_orca"), os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "chromophores", "output_orca", ), ) run_MorphCT.simulation( **parameters) # Execute MorphCT using these simulation parameters # The output dictionary from this fixing fix_dict = {} # Load the output pickle output_pickle_data = hf.load_pickle( os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), )) fix_dict["output_AA_morphology_dict"] = output_pickle_data[0] fix_dict["output_CG_morphology_dict"] = output_pickle_data[1] fix_dict["output_CG_to_AAID_master"] = output_pickle_data[2] fix_dict["output_parameter_dict"] = output_pickle_data[3] fix_dict["output_chromophore_list"] = output_pickle_data[4] # Load the expected pickle expected_pickle_data = hf.load_pickle( os.path.join( input_morph_dir, "TI", morphology.replace(".xml", "_post_calculate_transfer_integrals.pickle"), )) fix_dict["expected_AA_morphology_dict"] = expected_pickle_data[0] fix_dict["expected_CG_morphology_dict"] = expected_pickle_data[1] fix_dict["expected_CG_to_AAID_master"] = expected_pickle_data[2] fix_dict["expected_parameter_dict"] = expected_pickle_data[3] fix_dict["expected_chromophore_list"] = expected_pickle_data[4] return fix_dict
def __init__(self, **kwargs): parameter_dict = {} # Read in all of the keyword arguments from the par file for key, value in kwargs.items(): self.__dict__[key] = value # Obtain the slurm job ID (if there is one) self.slurm_job_ID = self.get_slurm_ID() # Parse the parameter file to get more useful file locations if self.morphology is not None: self.input_morphology_file = os.path.join(self.input_morph_dir, self.morphology) self.output_morphology_directory = os.path.join( self.output_morph_dir, os.path.splitext(self.morphology)[0]) if (self.output_orca_dir is not None) and len(self.output_orca_dir) > 0: self.output_orca_directory = os.path.join( self.output_orca_dir, os.path.splitext(self.morphology)[0]) else: self.output_orca_directory = self.output_morphology_directory if self.device_morphology is not None: self.input_device_file = os.path.join(self.input_device_dir, self.device_morphology) self.output_device_directory = os.path.join( self.output_device_dir, self.device_morphology) # Add all the parameters to the parameterDict, which will be used to # send everything between classes for key, value in self.__dict__.items(): if key in ["os", "sys"]: continue parameter_dict[key] = value # Make the correct directory tree self.make_dir_tree() if self.morphology is not None: # Copy the current code and the parameter file for safekeeping self.copy_code() if self.execute_fine_graining is False: # Load any previous data to allow us to run individual phases try: pickle_data = hf.load_pickle( os.path.join( self.output_morphology_directory, "code", "".join([ os.path.splitext(self.morphology)[0], ".pickle", ]), )) AA_morphology_dict = pickle_data[0] CG_morphology_dict = pickle_data[1] CG_to_AAID_master = pickle_data[2] previous_parameter_dict = pickle_data[3] chromophore_list = pickle_data[4] # Load in any parameters from the previous_parameter_dict # that have not been already defined in the new # parameter_dict (e.g. CG_type_mappings): for key, previous_value in previous_parameter_dict.items(): if key not in list(parameter_dict.keys()): parameter_dict[key] = previous_value # We need to make sure that the most up-to-date parameters # for this system (parameter_dict) gets correctly passed # on to the child processes. We do this by re-saving the # pickle using these new parameters. pickle_name = os.path.join( parameter_dict["output_morph_dir"], os.path.splitext(parameter_dict["morphology"])[0], "code", "".join([ os.path.splitext(parameter_dict["morphology"])[0], ".pickle", ]), ) hf.write_pickle( ( AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list, ), pickle_name, ) except: print( "PICKLE NOT FOUND, EXECUTING FINE GRAINING TO OBTAIN REQUIRED" " PARAMETERS...") self.execute_fine_graining = True # Now begin running the code based on user's flags if self.execute_fine_graining is True: print("---=== BACKMAPPING COARSE-GRAINED SITES... ===---") returned_data = fine_grainer.morphology( self.input_morphology_file, os.path.splitext(self.morphology)[0], parameter_dict, [], ).analyse_morphology() AA_morphology_dict = returned_data[0] CG_morphology_dict = returned_data[1] CG_to_AAID_master = returned_data[2] parameter_dict = returned_data[3] chromophore_list = returned_data[4] print("---=== BACKMAPPING COMPLETED ===---") if self.execute_molecular_dynamics is True: print("---=== EQUILIBRATING FINE-GRAINED MORPHOLOGY... ===---") returned_data = run_HOOMD.main( AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list, ) AA_morphology_dict = returned_data[0] CG_morphology_dict = returned_data[1] CG_to_AAID_master = returned_data[2] parameter_dict = returned_data[3] chromophore_list = returned_data[4] print("---=== EQUILIBRATION COMPLETED ===---") if self.execute_obtain_chromophores is True: print( "---=== IDENTIFYING CHROMOPHORES OF CHARGE CARRIER DELOCALISATION" "... ===---") returned_data = obtain_chromophores.main( AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list, ) AA_morphology_dict = returned_data[0] CG_morphology_dict = returned_data[1] CG_to_AAID_master = returned_data[2] parameter_dict = returned_data[3] chromophore_list = returned_data[4] print("---=== IDENTIFICATION COMPLETED ===---") if self.execute_ZINDO is True: print( "---=== PERFORMING SEMI-EMPIRICAL ZINDO/S CALCULATIONS... ===---" ) returned_data = execute_ZINDO.main( AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list, ) AA_morphology_dict = returned_data[0] CG_morphology_dict = returned_data[1] CG_to_AAID_master = returned_data[2] parameter_dict = returned_data[3] chromophore_list = returned_data[4] print("---=== CALCULATIONS COMPLETED ===---") if self.execute_calculate_transfer_integrals is True: print( "---=== DETERMINING ELECTRONIC TRANSFER INTEGRALS... ===---" ) returned_data = transfer_integrals.main( AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list, ) AA_morphology_dict = returned_data[0] CG_morphology_dict = returned_data[1] CG_to_AAID_master = returned_data[2] parameter_dict = returned_data[3] chromophore_list = returned_data[4] print("---=== DETERMINATION COMPLETED ===---") if self.remove_orca_inputs is True: print( "remove_orca_inputs is True. Cleaning up orca input dir..." ) orca_input_dir = os.path.join(self.output_orca_directory, "chromophores", "input_orca") try: shutil.rmtree(orca_input_dir) except FileNotFoundError: print("Directory already empty. Continuing...") if self.remove_orca_outputs is True: print( "remove_orca_outputs is True. Cleaning up orca output dir..." ) orca_output_dir = os.path.join( self.output_orca_directory, "chromophores", "output_orca", ) try: shutil.rmtree(orca_output_dir) except FileNotFoundError: print("Directory already empty. Continuing...") if self.execute_calculate_mobility is True: print( "---=== EXECUTING KINETIC MONTE CARLO MOBILITY SIMULATIONS..." " ===---") returned_data = mobility_KMC.main( AA_morphology_dict, CG_morphology_dict, CG_to_AAID_master, parameter_dict, chromophore_list, ) AA_morphology_dict = returned_data[0] CG_morphology_dict = returned_data[1] CG_to_AAID_master = returned_data[2] parameter_dict = returned_data[3] chromophore_list = returned_data[4] print("---=== EXECUTION COMPLETED ===---") else: # NEED TO PUT A CHECK IN HERE TO ENSURE THAT WE LOAD THE CORRECT MOLECULAR # DATA IN if self.execute_device_simulation is True: print( "---=== EXECUTING KINETIC MONTE CARLO DEVICE SIMULATIONS... ===---" ) device_KMC.main(parameter_dict) print("---=== EXECUTION COMPLETED ===---")
def test_outputs_import(self, run_simulation): (directory, pickle_file) = run_simulation if ".pickle" not in pickle_file: pickle_file = "".join( [pickle_file, "/code/", pickle_file, ".pickle"]) hf.load_pickle(os.path.join(directory, pickle_file))
# and then feed the child process a new seed from the random number # stream. This way, we ensure that each child process has a different # random number stream to the other processes, but it's the same stream # every time we run the program. child_seed = np.random.randint(0, 2**32) # Previous run command: run_command = [ "python", SINGLE_RUN_DEVICE_KMC_FILE, output_dir, str(proc_ID), str(child_seed), ] print(run_command) running_jobs.append(sp.Popen(run_command)) # Wait for all jobs to complete [p.wait() for p in running_jobs] print("All KMC jobs completed!") # Combine results if required. if __name__ == "__main__": try: pickle_file = sys.argv[1] except: print( "Please specify the pickle file to load to continue the pipeline from" " this point.") _, _, _, parameter_dict, _ = hf.load_pickle(pickle_file) main(parameter_dict)
def run_simulation(): # ---==============================================--- # ---======== Directory and File Structure ========--- # ---==============================================--- input_morph_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_morph_dir = os.path.join(TEST_ROOT, "output_MKMC") output_orca_dir = None input_device_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_device_dir = os.path.join(TEST_ROOT, "output_MKMC") # ---==============================================--- # ---========== Input Morphology Details ==========--- # ---==============================================--- morphology = "donor_polymer.xml" input_sigma = 3.0 device_morphology = None device_components = {} overwrite_current_data = True random_seed_override = 929292929 # ---==============================================--- # ---============= Execution Modules ==============--- # ---==============================================--- execute_fine_graining = False # Requires: None execute_molecular_dynamics = False # Requires: fine_graining execute_obtain_chromophores = ( False) # Requires: Atomistic morphology, or molecular_dynamics execute_ZINDO = False # Requires: obtain_chromophores execute_calculate_transfer_integrals = False # Requires: execute_ZINDO execute_calculate_mobility = True # Requires: calculate_transfer_integrals execute_device_simulation = ( False ) # Requires: calculate_transfer_integrals for all device_components # ---==============================================--- # ---=== General Kinetic Monte Carlo Parameters ===--- # ---==============================================--- # ---=== Universal KMC Parameters ===--- system_temperature = 290 use_simple_energetic_penalty = False record_carrier_history = True use_VRH = True # ---=== Mobility Specific KMC Parameters ===--- number_of_holes_per_simulation_time = 10 number_of_electrons_per_simulation_time = 0 hop_limit = 0 simulation_times = [1.00e-13, 1.00e-12, 1.00e-11] combine_KMC_results = True use_average_hop_rates = False average_intra_hop_rate = 8.07E14 average_inter_hop_rate = 3.92E14 # ---==============================================--- # ---================= Begin run ==================--- # ---==============================================--- parameter_file = os.path.realpath(__file__) # Force serial running proc_IDs = [0] parameter_names = [ i for i in dir() if (not i.startswith("__")) and ( not i.startswith("@")) and (not i.startswith("Test")) and ( not i.startswith("test")) and (i not in [ "run_MorphCT", "helper_functions", "hf", "os", "shutil", "TestCommand", "TEST_ROOT", "setup_module", "teardown_module", "testing_tools", "sys", "pytest", "pickle", ]) ] parameters = {} for name in parameter_names: parameters[name] = locals()[name] # ---==============================================--- # ---=============== Setup Prereqs ================--- # ---==============================================--- try: shutil.rmtree(output_morph_dir) except OSError: pass os.makedirs( os.path.join(output_morph_dir, os.path.splitext(morphology)[0], "code")) shutil.copy( os.path.join( TEST_ROOT, "assets", os.path.splitext(morphology)[0], "MKMC", morphology.replace(".xml", "_post_calculate_transfer_integrals.pickle"), ), os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), ), ) run_MorphCT.simulation( **parameters) # Execute MorphCT using these simulation parameters # The output dictionary from this fixing fix_dict = {} # Load the output pickle output_pickle_data = hf.load_pickle( os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), )) fix_dict["output_AA_morphology_dict"] = output_pickle_data[0] fix_dict["output_CG_morphology_dict"] = output_pickle_data[1] fix_dict["output_CG_to_AAID_master"] = output_pickle_data[2] fix_dict["output_parameter_dict"] = output_pickle_data[3] fix_dict["output_chromophore_list"] = output_pickle_data[4] # Load the expected pickle expected_pickle_data = hf.load_pickle( os.path.join( input_morph_dir, "MKMC", morphology.replace(".xml", "_post_calculate_mobility.pickle"), )) fix_dict["expected_AA_morphology_dict"] = expected_pickle_data[0] fix_dict["expected_CG_morphology_dict"] = expected_pickle_data[1] fix_dict["expected_CG_to_AAID_master"] = expected_pickle_data[2] fix_dict["expected_parameter_dict"] = expected_pickle_data[3] fix_dict["expected_chromophore_list"] = expected_pickle_data[4] return fix_dict
def run_simulation(): # ---==============================================--- # ---======== Directory and File Structure ========--- # ---==============================================--- input_morph_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_morph_dir = os.path.join(TEST_ROOT, "output_RH") output_orca_dir = None input_device_dir = os.path.join(TEST_ROOT, "assets", "donor_polymer") output_device_dir = os.path.join(TEST_ROOT, "output_RH") # ---==============================================--- # ---========== Input Morphology Details ==========--- # ---==============================================--- morphology = "donor_polymer.xml" input_sigma = 3.0 device_morphology = None device_components = {} overwrite_current_data = True random_seed_override = 929292929 # ---==============================================--- # ---============= Execution Modules ==============--- # ---==============================================--- execute_fine_graining = False # Requires: None execute_molecular_dynamics = True # Requires: fine_graining execute_obtain_chromophores = ( False) # Requires: Atomistic morphology, or molecular_dynamics execute_ZINDO = False # Requires: obtain_chromophores execute_calculate_transfer_integrals = False # Requires: execute_ZINDO execute_calculate_mobility = False # Requires: calculate_transfer_integrals execute_device_simulation = ( False ) # Requires: calculate_transfer_integrals for all device_components # ---==============================================--- # ---=========== Forcefield Parameters ============--- # ---==============================================--- CG_to_template_dirs = { "A": os.path.join(TEST_ROOT, "assets", "donor_polymer"), "B": os.path.join(TEST_ROOT, "assets", "donor_polymer"), "C": os.path.join(TEST_ROOT, "assets", "donor_polymer"), } CG_to_template_force_fields = { "A": "test_FF.xml", "B": "test_FF.xml", "C": "test_FF.xml", } pair_r_cut = 10.0 pair_dpd_gamma_val = 0.0 # ---==============================================--- # ---===== Molecular Dynamics Phase Parameters ====--- # ---==============================================--- number_of_phases = 4 temperatures = [1.0] taus = [1.0] pair_types = ["none", "dpd", "lj", "lj", "lj", "lj", "lj", "lj"] bond_types = ["harmonic"] angle_types = ["harmonic"] dihedral_types = ["opls"] integration_targets = ["all"] timesteps = [1E-3, 1E-3, 1E-7, 1E-4] durations = [1E5, 5E4, 1E4, 5E4] termination_conditions = ["ke_min", "max_t", "max_t", "max_t"] group_anchorings = ["all", "all", "all", "none"] dcd_file_write = True dcd_file_dumpsteps = [0] # ---==============================================--- # ---================= Begin run ==================--- # ---==============================================--- parameter_file = os.path.realpath(__file__) proc_IDs = hf.get_CPU_cores() parameter_names = [ i for i in dir() if (not i.startswith("__")) and ( not i.startswith("@")) and (not i.startswith("Test")) and ( not i.startswith("test")) and (i not in [ "run_MorphCT", "helper_functions", "hf", "os", "shutil", "TestCommand", "TEST_ROOT", "setup_module", "teardown_module", "testing_tools", "sys", "pytest", ]) ] parameters = {} for name in parameter_names: parameters[name] = locals()[name] # ---==============================================--- # ---=============== Setup Prereqs ================--- # ---==============================================--- try: shutil.rmtree(output_morph_dir) except OSError: pass os.makedirs( os.path.join(output_morph_dir, os.path.splitext(morphology)[0], "code")) shutil.copy( os.path.join( TEST_ROOT, "assets", os.path.splitext(morphology)[0], "RH", morphology.replace(".xml", "_post_fine_graining.pickle"), ), os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), ), ) run_MorphCT.simulation( **parameters) # Execute MorphCT using these simulation parameters # The output dictionary from this fixing fix_dict = {} # Load the output pickle output_pickle_data = hf.load_pickle( os.path.join( output_morph_dir, os.path.splitext(morphology)[0], "code", morphology.replace(".xml", ".pickle"), )) fix_dict["output_AA_morphology_dict"] = output_pickle_data[0] fix_dict["output_CG_morphology_dict"] = output_pickle_data[1] fix_dict["output_CG_to_AAID_master"] = output_pickle_data[2] fix_dict["output_parameter_dict"] = output_pickle_data[3] fix_dict["output_chromophore_list"] = output_pickle_data[4] # Load the expected pickle expected_pickle_data = hf.load_pickle( os.path.join(input_morph_dir, "RH", morphology.replace(".xml", "_post_run_HOOMD.pickle"))) fix_dict["expected_AA_morphology_dict"] = expected_pickle_data[0] fix_dict["expected_CG_morphology_dict"] = expected_pickle_data[1] fix_dict["expected_CG_to_AAID_master"] = expected_pickle_data[2] fix_dict["expected_parameter_dict"] = expected_pickle_data[3] fix_dict["expected_chromophore_list"] = expected_pickle_data[4] return fix_dict