def workflow_derivative_couplings(workflow_settings: Dict): """ Compute the derivative couplings from an MD trajectory. :param workflow_settings: Arguments to compute the oscillators see: `data/schemas/derivative_couplings.json :returns: None """ # Arguments to compute the orbitals and configure the workflow. see: # `data/schemas/general_settings.json config = workflow_settings['general_settings'] # Dictionary containing the general configuration config.update(initialize(**config)) # compute the molecular orbitals mo_paths_hdf5 = calculate_mos(**config) # Overlap matrix at two different times promised_overlaps = calculate_overlap( config['project_name'], config['path_hdf5'], config['dictCGFs'], config['geometries'], mo_paths_hdf5, config['hdf5_trans_mtx'], config['enumerate_from'], workflow_settings['overlaps_deph'], nHOMO=workflow_settings['nHOMO'], couplings_range=workflow_settings['couplings_range']) # Create a function that returns a proxime array of couplings schedule_couplings = schedule(lazy_couplings) # Calculate Non-Adiabatic Coupling promised_crossing_and_couplings = schedule_couplings( promised_overlaps, config['path_hdf5'], config['project_name'], config['enumerate_from'], workflow_settings['nHOMO'], workflow_settings['dt'], workflow_settings['tracking'], workflow_settings['write_overlaps'], algorithm=workflow_settings['algorithm']) # Write the results in PYXAID format work_dir = config['work_dir'] path_hamiltonians = join(work_dir, 'hamiltonians') if not os.path.exists(path_hamiltonians): os.makedirs(path_hamiltonians) # Inplace scheduling of write_hamiltonians function. # Equivalent to add @schedule on top of the function schedule_write_ham = schedule(write_hamiltonians) # Number of matrix computed nPoints = len(config['geometries']) - 2 # Write Hamilotians in PYXAID format promise_files = schedule_write_ham( config['path_hdf5'], mo_paths_hdf5, promised_crossing_and_couplings, nPoints, path_dir_results=path_hamiltonians, enumerate_from=config['enumerate_from'], nHOMO=workflow_settings['nHOMO'], couplings_range=workflow_settings['couplings_range']) run(promise_files, folder=work_dir) remove_folders(config['folders'])
def workflow_stddft(config: dict) -> None: """ Compute the excited states using simplified TDDFT :param workflow_settings: Arguments to compute the oscillators see: `data/schemas/absorption_spectrum.json :returns: None """ # Dictionary containing the general configuration config.update(initialize(config)) # Single Point calculations settings using CP2K mo_paths_hdf5, energy_paths_hdf5 = unpack(calculate_mos(config), 2) # Read structures molecules_au = [ change_mol_units(parse_string_xyz(gs)) for i, gs in enumerate(config.geometries) if (i % config.stride) == 0 ] # Noodles promised call scheduleTDDFT = schedule(compute_excited_states_tddft) results = gather(*[ scheduleTDDFT(config, mo_paths_hdf5[i], DictConfig({ 'i': i * config.stride, 'mol': mol })) for i, mol in enumerate(molecules_au) ]) return run(gather(results, energy_paths_hdf5), folder=config['workdir'])
def workflow_stddft(config: dict) -> None: """ Compute the excited states using simplified TDDFT :param workflow_settings: Arguments to compute the oscillators see: `data/schemas/absorption_spectrum.json :returns: None """ # Dictionary containing the general configuration config.update(initialize(config)) # Single Point calculations settings using CP2K mo_paths_hdf5, energy_paths_hdf5 = unpack(calculate_mos(config), 2) # Read structures molecules_au = [change_mol_units(parse_string_xyz(gs)) for i, gs in enumerate(config.geometries) if (i % config.stride) == 0] # Noodles promised call scheduleTDDFT = schedule(compute_excited_states_tddft) results = gather( *[scheduleTDDFT(config, mo_paths_hdf5[i], DictConfig( {'i': i * config.stride, 'mol': mol})) for i, mol in enumerate(molecules_au)]) return run(gather(results, energy_paths_hdf5), folder=config['workdir'])
def workflow_oscillator_strength(workflow_settings: Dict): """ Compute the oscillator strength. :param workflow_settings: Arguments to compute the oscillators see: `data/schemas/absorption_spectrum.json :returns: None """ # Arguments to compute the orbitals and configure the workflow. see: # `data/schemas/general_settings.json config = workflow_settings['general_settings'] # Dictionary containing the general configuration config.update(initialize(**config)) # Point calculations Using CP2K mo_paths_hdf5 = calculate_mos(**config) # geometries in atomic units molecules_au = [change_mol_units(parse_string_xyz(gs)) for gs in config['geometries']] # Construct initial and final states ranges transition_args = [workflow_settings[key] for key in ['initial_states', 'final_states', 'nHOMO']] initial_states, final_states = build_transitions(*transition_args) # Make a promise object the function the compute the Oscillator Strenghts scheduleOscillator = schedule(calc_oscillator_strenghts) oscillators = gather( *[scheduleOscillator( i, mol, mo_paths_hdf5, initial_states, final_states, config) for i, mol in enumerate(molecules_au) if i % workflow_settings['calculate_oscillator_every'] == 0]) energies, promised_cross_section = create_promised_cross_section( oscillators, workflow_settings['broadening'], workflow_settings['energy_range'], workflow_settings['convolution'], workflow_settings['calculate_oscillator_every']) cross_section, data = run( gather(promised_cross_section, oscillators), folder=config['work_dir']) return store_data(data, energies, cross_section)
def workflow_derivative_couplings(config: dict) -> list: """ Compute the derivative couplings from an MD trajectory. :param workflow_settings: Arguments to compute the oscillators see: `nac/workflows/schemas.py :returns: None """ # Dictionary containing the general configuration config.update(initialize(config)) logger.info("starting couplings calculation!") # compute the molecular orbitals mo_paths_hdf5, energy_paths_hdf5 = unpack(calculate_mos(config), 2) # mo_paths_hdf5 = run(calculate_mos(config), folder=config.workdir) # Overlap matrix at two different times promised_overlaps = calculate_overlap(config, mo_paths_hdf5) # Calculate Non-Adiabatic Coupling promised_crossing_and_couplings = lazy_couplings(config, promised_overlaps) # Write the results in PYXAID format config.path_hamiltonians = create_path_hamiltonians(config.workdir) # Inplace scheduling of write_hamiltonians function. # Equivalent to add @schedule on top of the function schedule_write_ham = schedule(write_hamiltonians) # Number of matrix computed config["nPoints"] = len(config.geometries) - 2 # Write Hamilotians in PYXAID format promise_files = schedule_write_ham( config, promised_crossing_and_couplings, mo_paths_hdf5) results = run( gather(promise_files, energy_paths_hdf5), folder=config.workdir, always_cache=False) remove_folders(config.folders) return results
def workflow_derivative_couplings(config: dict) -> list: """ Compute the derivative couplings from an MD trajectory. :param workflow_settings: Arguments to compute the oscillators see: `nac/workflows/schemas.py :returns: None """ # Dictionary containing the general configuration config.update(initialize(config)) logger.info("starting!") # compute the molecular orbitals mo_paths_hdf5, energy_paths_hdf5 = unpack(calculate_mos(config), 2) # mo_paths_hdf5 = run(calculate_mos(config), folder=config.workdir) # Overlap matrix at two different times promised_overlaps = calculate_overlap(config, mo_paths_hdf5) # Calculate Non-Adiabatic Coupling promised_crossing_and_couplings = lazy_couplings(config, promised_overlaps) # Write the results in PYXAID format config.path_hamiltonians = create_path_hamiltonians(config.workdir) # Inplace scheduling of write_hamiltonians function. # Equivalent to add @schedule on top of the function schedule_write_ham = schedule(write_hamiltonians) # Number of matrix computed config["nPoints"] = len(config.geometries) - 2 # Write Hamilotians in PYXAID format promise_files = schedule_write_ham( config, promised_crossing_and_couplings, mo_paths_hdf5) results = run(gather(promise_files, energy_paths_hdf5), folder=config.workdir) remove_folders(config.folders) return results
def workflow_single_points(config: dict) -> list: """ Single point calculations for a given trajectory :param workflow_settings: Arguments to run the single points calculations see: `nac/workflows/schemas.py """ # Dictionary containing the general configuration config.update(initialize(config)) logger.info("starting!") # compute the molecular orbitals # Unpack mo_paths_hdf5 = calculate_mos(config) # Pack results = run(mo_paths_hdf5, folder=config.workdir) return results
def calculate_couplings_and_oscillators(): """ Compute a couple of couplings with the Levine algorithm using precalculated MOs. """ initial_config = initialize(project_name, path_traj_xyz, basisname=basisname, path_basis=None, path_potential=None, enumerate_from=0, calculate_guesses='first', path_hdf5=path_test_hdf5, scratch_path=scratch_path) generate_pyxaid_hamiltonians('cp2k', project_name, cp2k_main, guess_args=cp2k_guess, nHOMO=50, couplings_range=(50, 30), **initial_config) data = workflow_oscillator_strength( 'cp2k', project_name, cp2k_main, guess_args=cp2k_guess, nHOMO=50, couplings_range=(50, 30), initial_states=[50], energy_range=(0, 5), # eV final_states=[[52]], **initial_config) return data
def workflow_electron_transfer(workflow_settings: Dict): """ Use a MD trajectory to calculate the Electron transfer rate. :param workflow_settings: Arguments to compute the oscillators see: `data/schemas/electron_transfer.json :returns: None """ # Arguments to compute the orbitals and configure the workflow. see: # `data/schemas/general_settings.json config = workflow_settings['general_settings'] # Dictionary containing the general configuration config.update(initialize(**config)) # Point calculations Using CP2K mo_paths_hdf5 = calculate_mos(**config) # geometries in atomic units molecules_au = [ change_mol_units(parse_string_xyz(gs)) for gs in config['geometries'] ] # Time-dependent coefficients path_time_coeffs = workflow_settings['path_time_coeffs'] time_depend_coeffs = read_time_dependent_coeffs(path_time_coeffs) msg = "Reading time_dependent coefficients from: {}".format( path_time_coeffs) logger.info(msg) # compute_overlaps_ET scheduled_overlaps = schedule(compute_overlaps_ET) fragment_overlaps = scheduled_overlaps( config['project_name'], molecules_au, config['basis_name'], config['path_hdf5'], config['dictCGFs'], mo_paths_hdf5, workflow_settings['fragment_indices'], config['enumerate_from'], config['package_name']) # Delta time in a.u. dt = workflow_settings['dt'] dt_au = dt * femtosec2au # Indices relation between the PYXAID active space and the orbitals # stored in the HDF5 args_map_index = [ workflow_settings[key] for key in ['orbitals_range', 'pyxaid_HOMO', 'pyxaid_Nmin', 'pyxaid_Nmax'] ] map_index_pyxaid_hdf5 = create_map_index_pyxaid(*args_map_index) # Number of points in the pyxaid trajectory: # shape: (initial_conditions, n_points, n_states) n_points = len(config['geometries']) - 2 # Read the swap between Molecular orbitals obtained from a previous # Coupling calculation swaps = read_swaps(['path_hdf5'], ['project_name']) # Electron transfer rate for each frame of the Molecular dynamics scheduled_photoexcitation = schedule(compute_photoexcitation) etrs = scheduled_photoexcitation(config['path_hdf5'], time_depend_coeffs, fragment_overlaps, map_index_pyxaid_hdf5, swaps, n_points, ['pyxaid_iconds'], dt_au) # Execute the workflow electronTransferRates, path_overlaps = run(gather(etrs, fragment_overlaps), folder=config['work_dir']) for i, mtx in enumerate(electronTransferRates): write_ETR(mtx, dt, i) write_overlap_densities(config['path_hdf5'], path_overlaps, swaps, dt)