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 example_FDE_fragments(): # For the purpose of the example, define xyz files here: xyz1 = io.StringIO('''3 O 0.00000000000000 -2.29819386240000 1.63037963360000 H -0.76925379540000 -2.28223123190000 2.22684542850000 H 0.76925379540000 -2.28223123190000 2.22684542850000''') xyz2 = io.StringIO('''3 O 0.00000000000000 2.29819386240000 1.63037963360000 H -0.76925379540000 2.28223123190000 2.22684542850000 H 0.76925379540000 2.28223123190000 2.22684542850000''') xyz3 = io.StringIO('''3 O 0.00000000000000 0.00000000000000 -0.26192472620000 H 0.00000000000000 0.77162768440000 0.34261631290000 H 0.00000000000000 -0.77162768440000 0.34261631290000''') # Read the Molecule from file m_h2o_1 = Molecule() m_h2o_1.readxyz(xyz1, 1) m_h2o_2 = Molecule() m_h2o_2.readxyz(xyz2, 1) m_mol = Molecule() m_mol.readxyz(xyz3, 1) settings = Settings() settings.basis = 'SZ' settings.specific.adf.nosymfit = '' # Prepare first water fragment r_h2o_1 = adf(templates.singlepoint.overlay(settings), m_h2o_1, job_name="h2o_1") # Prepare second water fragment r_h2o_2 = adf(templates.singlepoint.overlay(settings), m_h2o_2, job_name="h2o_2") frags = gather(schedule(Fragment)(r_h2o_1, m_h2o_1, isfrozen=True), schedule(Fragment)(r_h2o_2, m_h2o_2, isfrozen=True), Fragment(None, m_mol)) job_fde = adf_fragmentsjob(templates.singlepoint. overlay(settings), frags, job_name="test_fde_fragments") # Perform FDE job and get dipole # This gets the dipole moment of the active subsystem only dipole_fde = run(job_fde.dipole) print('FDE dipole:', dipole_fde) return dipole_fde
def run_workflow_couplings(config: DictConfig) -> PromisedObject: """Run the derivative coupling workflow using `config`.""" # compute the molecular orbitals logger.info("starting couplings calculation!") mo_paths_hdf5, energy_paths_hdf5 = unpack(calculate_mos(config), 2) # 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, config.orbitals_type) # 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) return gather(promise_files, energy_paths_hdf5)
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 test_xenon_42_multi(): A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] C = schedule(sum)(gather_all(multiples)) machine = Machine( scheduler_adaptor='slurm', location='ssh://fs0.das5.cs.vu.nl/home/jhidding', credential=xenon.CertificateCredential( username='******', certfile='/home/johannes/.ssh/id_rsa'), jobs_properties={ 'xenon.adaptors.schedulers.ssh.strictHostKeyChecking': 'false' }) worker_config = XenonJobConfig( prefix=Path('/home/jhidding/.local/share/workon/mcfly'), working_dir='/home/jhidding/', time_out=1000000000000, verbose=False) # , options=['-C', 'TitanX', '--gres=gpu:1']) result = run_xenon(C, machine=machine, worker_config=worker_config, n_processes=2) print("The answer is:", result)
def single_stage_r2c(cfg, n1, direction='f', **args): k1_p = indent_code( generate_codelet(cfg, "r2c" + direction, n=n1, name="r2c{}_{}".format(direction, n1), opencl=True, **args)) return noodles.schedule("\n\n".join)(noodles.gather( macros_to_code(macros), k1_p))
def adf3fde_cycle(frags, caps, adf3fde_settings, fragment_settings, job_name='fde'): new_frags = [] for i, frag in enumerate(frags): frag.isfrozen = False new_frags.append(schedule(Fragment)(adf_fragmentsjob( adf3fde_settings, frags, caps, fragment_settings, job_name=job_name + '_' + str(i)), frag.mol, pack_tape=True)) frag.isfrozen = True return gather(*new_frags)
def adf3fde(frags, caps, settings, fde_settings, fragment_settings, cycles=1): adf3fde_settings = templates.singlepoint adf3fde_settings.specific.adf.allow = "partialsuperfrags" if settings: adf3fde_settings = settings.overlay(adf3fde_settings) adf3fde_settings.specific.adf.fde = fde_settings for i in range(cycles): frags = adf3fde_cycle( frags, caps, adf3fde_settings, fragment_settings, job_name='fde_' + str(i)) return schedule(ADF3FDE_Result)(frags, caps)
def test_xenon_42_simple(xenon_server): A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] C = schedule(sum)(gather_all(multiples)) machine = Machine() worker_config = XenonJobConfig(verbose=True) result = run_xenon_simple(C, machine=machine, worker_config=worker_config) assert (result == 42)
def adf3fde(frags, caps, settings, fde_settings, fragment_settings, cycles=1): adf3fde_settings = templates.singlepoint adf3fde_settings.specific.adf.allow = "partialsuperfrags" if settings: adf3fde_settings = settings.overlay(adf3fde_settings) adf3fde_settings.specific.adf.fde = fde_settings for i in range(cycles): frags = adf3fde_cycle(frags, caps, adf3fde_settings, fragment_settings, job_name='fde_' + str(i)) return schedule(ADF3FDE_Result)(frags, caps)
def test_xenon_42_multi(xenon_server): A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] C = schedule(sum)(gather_all(multiples)) machine = Machine() worker_config = XenonJobConfig(queue_name='multi', verbose=True) result = run_xenon(C, machine=machine, worker_config=worker_config, n_processes=2) assert (result == 42)
def multi_stage_hc2hc(cfg, n1, n2, **args): k1_p = indent_code( generate_codelet(cfg, "r2cf", n=n1, name="notw{}".format(n1), opencl=True, **args)) k = indent_code( generate_codelet(cfg, "hc2hc", n=n2, name="twiddle{}".format(n2), opencl=True, **args)) return noodles.schedule("\n\n".join)(noodles.gather( macros_to_code(macros), indent_code(twiddle_const(n1, n2)), k1_p, k))
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 create_promised_cross_section(oscillators: List, broadening: float, energy_range: Tuple, convolution: str, calculate_oscillator_every: int): """ Create the function call that schedule the computation of the photoabsorption cross section """ # Energy grid in hartrees initial_energy = energy_range[0] final_energy = energy_range[1] npoints = 10 * (final_energy - initial_energy) // broadening energies = np.linspace(initial_energy, final_energy, npoints) # Compute the cross section schedule_cross_section = schedule(compute_cross_section_grid) return energies, schedule_cross_section(oscillators, convolution, energies, broadening, calculate_oscillator_every)
def adf3fde_cycle(frags, caps, adf3fde_settings, fragment_settings, job_name='fde'): new_frags = [] for i, frag in enumerate(frags): frag.isfrozen = False new_frags.append( schedule(Fragment)(adf_fragmentsjob(adf3fde_settings, frags, caps, fragment_settings, job_name=job_name + '_' + str(i)), frag.mol, pack_tape=True)) frag.isfrozen = True return gather(*new_frags)
def two_stage_kernel(cfg, n1, n2): k1_p = indent_code( generate_codelet(cfg, "notw_complex", n=n1, name="notw{}".format(n1), opencl=True)) k2_p = indent_code( generate_codelet(cfg, "twiddle_complex", n=n2, name="twiddle{}".format(n2), opencl=True)) k3 = two_stage_template.format(n=n1 * n2, n1=n1, n2=n2, n1s=2 * n1, n2s=2 * n2) return noodles.schedule("\n\n".join)(noodles.gather( macros_to_code(macros), indent_code(twiddle_const(n1, n2)), k1_p, k2_p, k3))
def run_partialcharges(results: Results, options: Options, promise: PromisedObject = None) -> dict: """ Compute partial charges """ opts = edit_calculator_options(options, ['esp2multipole', 'partialcharges']) if promise is not None: path_partialcharges = options.path_optionfiles / "partialcharges.xml" sections_to_edit = {"partialcharges": {"input": promise}} opts['partialcharges'] = schedule(edit_xml_file)( path_partialcharges, 'options', lift(sections_to_edit)) logger.info("Running CHELPG fit") args = create_promise_command("xtp_tools -e partialcharges -o {}", opts['partialcharges']) return call_xtp_cmd(args, options.scratch_dir / 'partialcharges', expected_output={})
def run_workflow_stddft(config: DictConfig) -> PromisedObject: """Compute the excited states using simplified TDDFT using `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 gather(results, energy_paths_hdf5)
def run_iqm(results: Results, options: Options, state: PromisedObject) -> dict: """Run the eqm jobs.""" # Copy option files src = ["mbgft.xml", "xtpdft.xml"] dst = ["mbgft_pair.xml", "xtpdft_pair.xml"] copy_option_files(options.path_optionfiles, src, dst) results['job_opts_iqm'] = edit_calculator_options( options, ['iqm', 'xtpdft_pair', 'mbgft_pair']) # replace optionfiles with its absolute path sections_to_edit = { '': { 'replace_regex_recursively': ('OPTIONFILES', to_posix(options.path_optionfiles)) } } edited_iqm_file = schedule(edit_xml_file)(results['job_opts_iqm']['iqm'], 'iqm', sections_to_edit) # write into state cmd_iqm_write = create_promise_command( "xtp_parallel -e iqm -o {} -f {} -s 0 -j write", edited_iqm_file, state) results['job_setup_iqm'] = call_xtp_cmd( cmd_iqm_write, options.scratch_dir / 'iqm', expected_output={'iqm_jobs': "iqm.jobs"}) # Select the number of jobs to run based on the input provided by the user results['job_select_iqm_jobs'] = edit_jobs_file( results['job_setup_iqm']['iqm_jobs'], options.iqm_jobs) return distribute_iqm_jobs(results, options, state)
def workflow_oscillator_strength( package_name: str, project_name: str, package_args: Dict, guess_args: Dict = None, geometries: List = None, dictCGFs: Dict = None, enumerate_from: int = 0, calc_new_wf_guess_on_points: str = None, path_hdf5: str = None, package_config: Dict = None, work_dir: str = None, initial_states: Any = None, final_states: Any = None, traj_folders: List = None, hdf5_trans_mtx: str = None, nHOMO: int = None, couplings_range: Tuple = None, calculate_oscillator_every: int = 50, convolution: str = 'gaussian', broadening: float = 0.1, # eV energy_range: Tuple = None, # eV geometry_units='angstrom', **kwargs): """ Compute the oscillator strength :param package_name: Name of the package to run the QM simulations. :param project_name: Folder name where the computations are going to be stored. :param geometry:string containing the molecular geometry. :param package_args: Specific settings for the package :param guess_args: Specific settings for guess calculate with `package`. :type package_args: dict :param initial_states: List of the initial Electronic states. :type initial_states: [Int] :param final_states: List containing the sets of possible electronic states. :type final_states: [[Int]] :param calc_new_wf_guess_on_points: Points where the guess wave functions are calculated. :param package_config: Parameters required by the Package. :param convolution: gaussian | lorentzian :param calculate_oscillator_every: step to compute the oscillator strengths :returns: None """ # Start logging event file_log = '{}.log'.format(project_name) logging.basicConfig(filename=file_log, level=logging.DEBUG, format='%(levelname)s:%(message)s %(asctime)s\n', datefmt='%m/%d/%Y %I:%M:%S %p') # Point calculations Using CP2K mo_paths_hdf5 = calculate_mos(package_name, geometries, project_name, path_hdf5, traj_folders, package_args, guess_args, calc_new_wf_guess_on_points, enumerate_from, package_config=package_config) # geometries in atomic units molecules_au = [ change_mol_units(parse_string_xyz(gs)) for gs in geometries ] # Construct initial and final states ranges initial_states, final_states = build_transitions(initial_states, final_states, nHOMO) # Schedule the function the compute the Oscillator Strenghts scheduleOscillator = schedule(calcOscillatorStrenghts) oscillators = gather(*[ scheduleOscillator(i, project_name, mo_paths_hdf5, dictCGFs, mol, path_hdf5, hdf5_trans_mtx=hdf5_trans_mtx, initial_states=initial_states, final_states=final_states) for i, mol in enumerate(molecules_au) if i % calculate_oscillator_every == 0 ]) energies, promised_cross_section = create_promised_cross_section( oscillators, broadening, energy_range, convolution, calculate_oscillator_every) cross_section, data = run(gather(promised_cross_section, oscillators), folder=work_dir) # Transform the energy to nm^-1 energies_nm = energies * 1240 # Save cross section np.savetxt( 'cross_section_cm.txt', np.stack((energies, energies_nm, cross_section, cross_section * 1e16), axis=1), header= 'Energy[eV] Energy[nm^-1] photoabsorption_cross_section[cm^2] photoabsorption_cross_section[^2]' ) # molar extinction coefficients (e in M-1 cm-1) nA = physical_constants['Avogadro constant'][0] cte = np.log(10) * 1e3 / nA extinction_coefficients = cross_section / cte np.savetxt( 'molar_extinction_coefficients.txt', np.stack((energies, energies_nm, extinction_coefficients), axis=1), header='Energy[eV] Energy[nm^-1] Extinction_coefficients[M^-1 cm^-1]') print("Data: ", data) print("Calculation Done") # Write data in human readable format write_information(data) return data
def generate_pyxaid_hamiltonians(package_name: str, project_name: str, package_args: Dict, guess_args: Dict = None, geometries: List = None, dictCGFs: Dict = None, calc_new_wf_guess_on_points: str = None, path_hdf5: str = None, enumerate_from: int = 0, package_config: Dict = None, dt: float = 1, traj_folders: List = None, work_dir: str = None, basisname: str = None, hdf5_trans_mtx: str = None, nHOMO: int = None, couplings_range: Tuple = None, algorithm='levine', ignore_warnings=False, tracking=True) -> None: """ Use a md trajectory to generate the hamiltonian components to run PYXAID nonadiabatic molecular dynamics. :param package_name: Name of the package to run the QM simulations. :param project_name: Folder name where the computations are going to be stored. :param package_args: Specific Settings for the package that will compute the MOs. :param geometries: List of string cotaining the molecular geometries numerical results. :paramter dictCGFS: Dictionary from Atomic Label to basis set :param calc_new_wf_guess_on_points: Calculate a guess wave function either in the first point or on each point of the trajectory. :param path_hdf5: path to the HDF5 file were the data is going to be stored. :param enumerate_from: Number from where to start enumerating the folders create for each point in the MD. :param hdf5_trans_mtx: Path into the HDF5 file where the transformation matrix (from Cartesian to sphericals) is stored. :param dt: Time used in the dynamics (femtoseconds) :param package_config: Parameters required by the Package. :type package_config: Dict :param nHOMO: index of the H**O orbital. :param couplings_range: Range of MO use to compute the nonadiabatic coupling matrix. :returns: None """ # Start logging event file_log = '{}.log'.format(project_name) logging.basicConfig(filename=file_log, level=logging.DEBUG, format='%(levelname)s:%(message)s %(asctime)s\n', datefmt='%m/%d/%Y %I:%M:%S %p') # Log initial config information log_config(work_dir, path_hdf5, algorithm) # prepare Cp2k Jobs # Point calculations Using CP2K mo_paths_hdf5 = calculate_mos(package_name, geometries, project_name, path_hdf5, traj_folders, package_args, guess_args, calc_new_wf_guess_on_points, enumerate_from, package_config=package_config, ignore_warnings=ignore_warnings) # Overlap matrix at two different times promised_overlaps = calculate_overlap(project_name, path_hdf5, dictCGFs, geometries, mo_paths_hdf5, hdf5_trans_mtx, enumerate_from, nHOMO=nHOMO, couplings_range=couplings_range) # Calculate Non-Adiabatic Coupling schedule_couplings = schedule(lazy_couplings) promised_crossing_and_couplings = schedule_couplings(promised_overlaps, path_hdf5, project_name, enumerate_from, nHOMO, dt, tracking, algorithm=algorithm) # Write the results in PYXAID format 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(geometries) - 2 # Write Hamilotians in PYXAID format promise_files = schedule_write_ham(path_hdf5, mo_paths_hdf5, promised_crossing_and_couplings, nPoints, path_dir_results=path_hamiltonians, enumerate_from=enumerate_from, nHOMO=nHOMO, couplings_range=couplings_range) run(promise_files, folder=work_dir) remove_folders(traj_folders)
def __getitem__(self, val): if isinstance(val, PromisedObject): return schedule(self.state[val]) else: return self.state[val]
def zip_with(): arr = np.random.normal(size=100) ys = patterns.map(lambda x: np.pi * x, arr) rs = patterns.zip_with(x_sin_pix, arr, ys) return schedule(np.allclose)(rs, arr * np.sin(np.pi * arr))
def calculate_ETR( package_name: str, project_name: str, package_args: Dict, path_time_coeffs: str=None, geometries: List=None, initial_conditions: List=None, path_hdf5: str=None, basis_name: str=None, enumerate_from: int=0, package_config: Dict=None, calc_new_wf_guess_on_points: str=None, guess_args: Dict=None, work_dir: str=None, traj_folders: List=None, dictCGFs: Dict=None, orbitals_range: Tuple=None, pyxaid_HOMO: int=None, pyxaid_Nmin: int=None, pyxaid_Nmax: int=None, fragment_indices: None=List, dt: float=1, **kwargs): """ Use a md trajectory to calculate the Electron transfer rate. :param package_name: Name of the package to run the QM simulations. :param project_name: Folder name where the computations are going to be stored. :param package_args: Specific settings for the package. :param path_hdf5: Path to the HDF5 file that contains the numerical results. :param geometries: List of string cotaining the molecular geometries. :paramter dictCGFS: Dictionary from Atomic Label to basis set :type dictCGFS: Dict String [CGF], CGF = ([Primitives], AngularMomentum), Primitive = (Coefficient, Exponent) :param calc_new_wf_guess_on_points: number of Computations that used a previous calculation as guess for the wave function. :param nHOMO: index of the H**O orbital. :param couplings_range: Range of MO use to compute the nonadiabatic :param pyxaid_range: range of HOMOs and LUMOs used by pyxaid. :param enumerate_from: Number from where to start enumerating the folders create for each point in the MD. :param traj_folders: List of paths to where the CP2K MOs are printed. :param package_config: Parameters required by the Package. :param fragment_indices: indices of atoms belonging to a fragment. :param dt: integration time used in the molecular dynamics. :returns: None """ # Start logging event file_log = '{}.log'.format(project_name) logging.basicConfig(filename=file_log, level=logging.DEBUG, format='%(levelname)s:%(message)s %(asctime)s\n', datefmt='%m/%d/%Y %I:%M:%S %p') # prepare Cp2k Job point calculations Using CP2K mo_paths_hdf5 = calculate_mos( package_name, geometries, project_name, path_hdf5, traj_folders, package_args, guess_args, calc_new_wf_guess_on_points, enumerate_from, package_config=package_config) # geometries in atomic units molecules_au = [change_mol_units(parse_string_xyz(gs)) for gs in geometries] # Time-dependent coefficients 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( project_name, molecules_au, basis_name, path_hdf5, dictCGFs, mo_paths_hdf5, fragment_indices, enumerate_from, package_name) # Delta time in a.u. dt_au = dt * femtosec2au # Indices relation between the PYXAID active space and the orbitals # stored in the HDF5 map_index_pyxaid_hdf5 = create_map_index_pyxaid( orbitals_range, pyxaid_HOMO, pyxaid_Nmin, pyxaid_Nmax) # Number of ETR points calculated with the MD trajectory n_points = len(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( path_hdf5, time_depend_coeffs, fragment_overlaps, map_index_pyxaid_hdf5, swaps, n_points, dt_au) # Execute the workflow electronTransferRates, path_overlaps = run( gather(etrs, fragment_overlaps), folder=work_dir) for i, mtx in enumerate(electronTransferRates): write_ETR(mtx, dt, i) write_overlap_densities(path_hdf5, path_overlaps, dt)
def calculate_overlap(project_name: str, path_hdf5: str, dictCGFs: Dict, geometries: List, mo_paths_hdf5: List, hdf5_trans_mtx: str, enumerate_from: int, overlaps_deph: bool, nHOMO: int = None, couplings_range: Tuple = None, units: str = 'angstrom') -> List: """ Calculate the Overlap matrices before computing the non-adiabatic coupling using 3 consecutive set of MOs in a molecular dynamic. :param path_hdf5: Path to the HDF5 file that contains the numerical results. :type path_hdf5: String :paramter dictCGFS: Dictionary from Atomic Label to basis set :type dictCGFS: Dict String [CGF], CGF = ([Primitives], AngularMomentum), Primitive = (Coefficient, Exponent) :param geometries: list of molecular geometries :param mo_paths: Path to the MO coefficients and energies in the HDF5 file. :param hdf5_trans_mtx: path to the transformation matrix in the HDF5 file. :param enumerate_from: Number from where to start enumerating the folders create for each point in the MD :type enumerate_from: Int :param nHOMO: index of the H**O orbital in the HDF5 :param couplings_range: range of Molecular orbitals used to compute the coupling. :returns: paths to the Overlap matrices inside the HDF5. """ nPoints = len(geometries) - 1 # Inplace scheduling of calculate_overlap function # Equivalent to add @schedule on top of the function schedule_overlaps = schedule(lazy_overlaps) # Compute the Overlaps paths_overlaps = [] for i in range(nPoints): # Extract molecules to compute couplings if overlaps_deph: molecules = tuple( map(lambda idx: parse_string_xyz(geometries[idx]), [0, i + 1])) else: molecules = tuple( map(lambda idx: parse_string_xyz(geometries[idx]), [i, i + 1])) # If units are Angtrom convert then to a.u. if 'angstrom' in units.lower(): molecules = tuple(map(change_mol_units, molecules)) # Compute the coupling overlaps = schedule_overlaps(i, project_name, path_hdf5, dictCGFs, molecules, mo_paths_hdf5, hdf5_trans_mtx=hdf5_trans_mtx, enumerate_from=enumerate_from, nHOMO=nHOMO, couplings_range=couplings_range) paths_overlaps.append(overlaps) # Gather all the promised paths return gather(*paths_overlaps)
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)
def fold_and_map(): arr = np.random.normal(size=100) xs = patterns.fold(aux_sum, 0, arr) ys = patterns.map(lambda x: x**2, xs) return schedule(np.allclose)(ys, np.cumsum(arr)**2)
print( "Next, as many threads as there are logical cores, taken from multiprocessing.cpu_count()." ) start_mt = time.time() my_q = queue.Queue() for i in range_of_values: my_q.put(i) procs = [ threading.Thread(target=worker, args=(my_q, )) for i in range(ncpus) ] for ps in procs: ps.start() for ps in procs: ps.join() end_mt = time.time() print() print("Now Noodles with as many threads as there are logical cores.") start_noodles = time.time() result = run_parallel(gather(*(schedule(sumPrimes_noodles)(x) for x in range_of_values)), n_threads=ncpus) for item in result: print(item) end_noodles = time.time() print() print("A single thread takes {0:.2f} seconds".format(end_st - start_st)) print("Multithreading takes {0:.2f} seconds".format(end_mt - start_mt)) print("Noodles takes {0:.2f} seconds".format(end_noodles - start_noodles))
def fun_ethylene(scratch_path): """ Test Ethylene singlw """ project_name = 'ethylene' # create Settings for the Cp2K Jobs s = Settings() s.basis = "DZVP-MOLOPT-SR-GTH" s.potential = "GTH-PBE" s.cell_parameters = [12.74] * 3 dft = s.specific.cp2k.force_eval.dft dft.scf.added_mos = 20 dft.scf.eps_scf = 1e-4 dft['print']['ao_matrices']['overlap'] = '' dft['print']['ao_matrices']['filename'] = join(scratch_path, 'overlap.out') # Copy the basis and potential to a tmp file shutil.copy('test/test_files/BASIS_MOLOPT', scratch_path) shutil.copy('test/test_files/GTH_POTENTIALS', scratch_path) # Cp2k configuration files basiscp2k = join(scratch_path, 'BASIS_MOLOPT') potcp2k = join(scratch_path, 'GTH_POTENTIALS') cp2k_config = {"basis": basiscp2k, "potential": potcp2k} # HDF5 path path_hdf5 = join(scratch_path, 'ethylene.hdf5') # all_geometries type :: [String] path_xyz = 'test/test_files/ethylene.xyz' geometries = split_file_geometries(path_xyz) # Input/Output Files file_xyz = join(scratch_path, 'coordinates.xyz') file_inp = join(scratch_path, 'ethylene.inp') file_out = join(scratch_path, 'ethylene.out') file_MO = join(scratch_path, 'mo_coeffs.out') files = JobFiles(file_xyz, file_inp, file_out, file_MO) schedule_job = schedule(prepare_job_cp2k) promise = schedule_job(geometries[0], files, s, scratch_path, project_name=project_name, hdf5_file=path_hdf5, wfn_restart_job=None, store_in_hdf5=True, nHOMOS=25, nLUMOS=25, package_config=cp2k_config) cp2k_result = run(promise) path_properties = cp2k_result.orbitals with h5py.File(path_hdf5) as f5: assert (all(p in f5 for p in path_properties))
zeta = 0.5 f = harmonic_oscillator(omega_0, zeta) t = np.linspace(0.0, 15.0, 4) # ~\~ end # ~\~ begin <<lit/paranoodles.md|noodlify>>[2] h = 0.01 @noodles.schedule def fine(x, t_0, t_1): return iterate_solution(forward_euler(f), h)(x, t_0, t_1) # ~\~ end # ~\~ begin <<lit/paranoodles.md|noodlify>>[3] y_euler = noodles.gather(*tabulate(noodles.schedule(fine), [1.0, 0.0], t)) # ~\~ end # ~\~ begin <<lit/paranoodles.md|noodlify>>[4] def paint(node, name): if name == "coarse": node.attr["fillcolor"] = "#cccccc" elif name == "fine": node.attr["fillcolor"] = "#88ff88" else: node.attr["fillcolor"] = "#ffffff" draw_workflow('seq-graph.svg', noodles.get_workflow(y_euler), paint)
def test_unwrap(): assert f == unwrap(schedule(f)) assert f == unwrap(f)