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_iterate(): a = noodles.delay((1,2,3)) b, c, d = a e = noodles.gather(d, c, b) result = noodles.run_single(e) assert result == (3, 2, 1)
def evaluate(self, fitness_evaluator): evaluate = [Chromosome(fitness=fitness_evaluator.evaluate(c.values), values=c.values, sigma=c.sigma) for c in self.individuals] self.individuals = gather(*evaluate) return self
def test_broker_02(): A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] C = accumulate(noodles.gather(*multiples)) assert run_single(C) == 42
def test_broker_01(): A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] C = accumulate(noodles.gather(*multiples)) assert run_parallel(C, 4) == 42
def test_sort(): a = [random_number() for i in range(10)] b = noodles.gather(*sorted(a)) result = noodles.run_single(b) print(result) assert result == sorted(result)
def test_hybrid_threaded_runner_03(): A = [delayed(1, 0.01) for i in range(8)] B = sum(gather(*A)) start = time.time() assert run_hybrid(B, selector, {1: single_worker()}) == 8 end = time.time() assert (end - start) > 0.08
def test_xenon_42(): A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] C = accumulate(noodles.gather(*multiples)) result = run_parallel_timing(C, 4, sys.stdout) assert(result == 42)
def test_broker_logging(): A = log_add(1, 1) B = sub(3, A) multiples = [mul(log_add(i, B), A) for i in range(6)] C = accumulate(noodles.gather(*multiples)) with NCDisplay(title="Running the test") as display: assert run_parallel_with_display(C, 4, display) == 42
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 test_prov_03(): db_file = "prov2.json" A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] C = accumulate(gather(*multiples)) result = run_parallel(C, 4, serial.base, db_file, JobKeeper(keep=True)) assert result == 42 os.unlink(db_file)
def test_prov_04(): db_file = "prov3.json" A = add2(1, 1) B = sub(3, A) multiples = [mul(add2(i, B), A) for i in range(6)] C = accumulate(gather(*multiples)) result = run_parallel_opt(C, 4, serial.base, db_file) assert result == 42 os.unlink(db_file)
def test_prov_02(): db_file = "prov1.json" A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] C = accumulate(gather(*multiples)) result = run_single(C, serial.base, db_file) assert result == 42 os.unlink(db_file)
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 mfcc(package, frags, caps, settings=None): mfcc_settings = templates.singlepoint if settings: mfcc_settings = mfcc_settings.overlay(settings) capped_atoms = {} for i, cap in enumerate(caps): for a in cap: capped_atoms[a.coords] = a for i, frag in enumerate(frags): cap_label = 'cap' + str(i + 1) for a in frag: if a.coords in capped_atoms: a.properties.name = cap_label capped_atoms[a.coords].properties.name = cap_label frag_jobs = [package(mfcc_settings, frag, job_name="mfcc_frag_" + str(i)) for i, frag in enumerate(frags)] cap_jobs = [package(mfcc_settings, cap, job_name="mfcc_cap_" + str(i)) for i, cap in enumerate(caps)] return MFCC_Result(gather(*frag_jobs), gather(*cap_jobs))
def runNoodles(jsonFile, logFolder, numThreads): global logFolderAbsPath logFolderAbsPath = os.path.abspath(logFolder) os.makedirs(logFolderAbsPath) input = json.load(open(jsonFile, 'r')) if input[0].get('task') is None: jobs = [make_job(td['command'], td['id'], td['exclude']) for td in input] else: jobs = [make_job(td['command'], td['task'], td['exclude']) for td in input] wf = noodles.gather(*jobs) with NCDisplay(error_filter) as display: run(wf, display=display, n_threads=numThreads)
def test_binder(): A = value(1) B = value(2) C = gather(A, B) C = get_workflow(C) A = get_workflow(A) B = get_workflow(B) assert is_workflow(C) assert C.nodes[C.root].bound_args.args == (Empty, Empty) assert (C.root, ArgumentAddress(ArgumentKind.variadic, 'a', 0)) \ in C.links[A.root] assert (C.root, ArgumentAddress(ArgumentKind.variadic, 'a', 1)) \ in C.links[B.root]
def test_hybrid_coroutine_runner_03(): A1 = [f(i) for i in range(11)] A2 = [g(i) for i in range(7)] B = sum(gather(*(A1+A2))) tic1, c1 = ticcer() tic2, c2 = ticcer() result = Scheduler().run( hybrid_coroutine_worker(selector, { 1: tic_worker(tic1), 2: tic_worker(tic2)}), get_workflow(B)) assert c1() == 11 assert c2() == 7 assert result == 173
def _parameter_sweep(self, parameter_space, kernel_options, device_options, tuning_options): """Build a Noodles workflow by sweeping the parameter space""" results = [] #randomize parameter space to do pseudo load balancing parameter_space = list(parameter_space) random.shuffle(parameter_space) #split parameter space into chunks work_per_thread = int(numpy.ceil(len(parameter_space) / float(self.max_threads))) chunks = _chunk_list(parameter_space, work_per_thread) for chunk in chunks: chunked_result = self._run_chunk(chunk, kernel_options, device_options, tuning_options) results.append(lift(chunked_result)) return gather(*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 example_partial_geometry_opt(): """ Performa partial optimization freezing the Hydrogen atoms """ methanol = molkit.from_smiles('CO') # optimize only H atoms s = Settings() s.freeze = [1, 2] geom_job1 = adf(templates.geometry.overlay(s), methanol, job_name='geom_job1').molecule # optimize only H atoms s = Settings() s.selected_atoms = ['H'] geom_job2 = adf(templates.geometry.overlay(s), methanol, job_name='geom_job2').molecule geom1, geom2 = run(gather(geom_job1, geom_job2), n_processes=1) return geom1, geom2
def test_hessian_transfer(): """ Test DFTB -> Orca hessian transfer """ h2o = molkit.from_smiles('O') h2o.properties.symmetry = 'C1' h2o_freq = dftb(templates.freq, h2o, job_name="freq").hessian s = Settings() s.inithess = h2o_freq h2o_opt = orca(templates.geometry.overlay(s), h2o, job_name="opt") energy = h2o_opt.energy dipole = h2o_opt.dipole wf = gather(energy, dipole) print(run(wf))
def test_xenon_42(): A = log_add(1, 1) B = sub(3, A) multiples = [mul(log_add(i, B), A) for i in range(6)] C = accumulate(noodles.gather(*multiples)) xenon_config = XenonConfig( jobs_scheme='local' ) job_config = RemoteJobConfig( registry=serial.base, time_out=1000 ) with XenonKeeper() as Xe, NCDisplay() as display: result = run_xenon( C, Xe, "cache.json", 2, xenon_config, job_config, display=display) assert(result == 42)
def example_freqs(): """ This examples illustrates the possibility to use different packages interchangeably. Analytical frequencies are not available for B3LYP in ADF This workflow captures the resulting error and submits the same job to ORCA. """ # Generate water molecule water = molkit.from_smiles('[OH2]', forcefield='mmff') # Pre-optimize the water molecule opt_water = dftb(templates.geometry, water, job_name="dftb_geometry") jobs = [] # Generate freq jobs for 3 functionals for functional in ['pbe', 'b3lyp', 'blyp']: s = Settings() s.basis = 'DZ' s.functional = functional # Try to perform the jobs with adf or orca, take result from first successful calculation freqjob = find_first_job(is_successful, [adf, orca], templates.freq.overlay(s), opt_water.molecule, job_name=functional) jobs.append(freqjob) # Run workflow results = run(gather(*jobs), n_processes=1) # extrac results freqs = [r.frequencies[-3:] for r in results] functionals = ['pbe', 'b3lyp', 'blyp'] # Print the result table = ["{:10s}{:10.3f}{:10.3f}{:10.3f}\n".format(fun, *fs) for fun, fs in zip(functionals, freqs)] print(table) return freqs
} # Check preoptimized molecules opt_mols = {n: skip_dftb(job, molecules[n]) for n, job in dftb_jobs.items()} # DFT optimization with Orca s = templates.geometry s.functional = 'BP86' s.basis = 'def2TZVP' dft_jobs = { n: orca(s, mol, job_name='orca_{}'.format(n)) for n, mol in opt_mols.items() } # TD-DFT ADF with COSMO s = templates.singlepoint s.functional = 'camy-b3lyp' s.basis = 'TZ2P' s.specific.adf.Solvation.solvent = 'name=Dichloromethane emp=0.0 neql=2.028' td_dft_jobs = { n: adf(s, job.molecule, job_name='td_dft_{}'.format(n)) for n, job in dft_jobs.items() } energies = [gather(n, j.energy) for n, j in td_dft_jobs.items()] result = run(gather(*energies), n_processes=4, folder='biphenyl') print(result)
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 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)
} # returns a set of results object containing the output of # each point in the scan LT = PES_scan(dftb, settings, product, scan) # Gets the object presenting the molecule # with the maximum energy calculated from the scan apprTS = select_max(LT, 'energy') # Run the TS optimization, using the default TS template TS = dftb(templates.ts.overlay(settings), apprTS.molecule) # Actual execution of the jobs reactives = [E_reactant, E_product, TS] E_reactant, E_product, TS = run(gather(*reactives), n_processes=1) # Retrieve the molecular coordinates mol = TS.molecule d1 = bond_distance(mol.atoms[0].coords, mol.atoms[1].coords) d2 = bond_distance(mol.atoms[3].coords, mol.atoms[4].coords) Eact = (TS.energy - E_ethene - E_reactant) * hartree2kcal Ereact = (E_product - E_ethene - E_reactant) * hartree2kcal result[smiles] = [Eact, Ereact, d1, d2] print("Reactant Eact Ereact Bond1 Bond2") for smiles in result: print("{0:20s} {1:7.1f} {2:7.1f} {3:7.2f} \ {4:7.2f}".format(smiles, *result[smiles]))
def calculate_mos(package_name: str = None, geometries: List = None, project_name: str = None, path_hdf5: str = None, folders: List = None, settings_main: Dict = None, settings_guess: Dict = None, calc_new_wf_guess_on_points: List = None, enumerate_from: int = 0, package_config: Dict = None, ignore_warnings=False, **kwargs) -> List: """ Look for the MO in the HDF5 file if they do not exists calculate them by splitting the jobs in batches given by the ``restart_chunk`` variables. Only the first job is calculated from scratch while the rest of the batch uses as guess the wave function of the first calculation in the batch. :param geometries: list of molecular geometries :param project_name: Name of the project used as root path for storing data in HDF5. :param path_hdf5: Path to the HDF5 file that contains the numerical results. :param folders: path to the directories containing the MO outputs :param settings_main: Settings for the job to run. :param calc_new_wf_guess_on_points: Calculate a new Wave function guess in each of the geometries indicated. By Default only an initial guess is computed. :param enumerate_from: Number from where to start enumerating the folders create for each point in the MD :returns: path to nodes in the HDF5 file to MO energies and MO coefficients. """ # First calculation has no initial guess guess_job = None # calculate the rest of the job using the previous point as initial guess orbitals = [] # list to the nodes in the HDF5 containing the MOs for j, gs in enumerate(geometries): # number of the point with respect to all the trajectory k = j + enumerate_from # Path where the MOs will be store in the HDF5 root = join(project_name, 'point_{}'.format(k), package_name, 'mo') hdf5_orb_path = [join(root, 'eigenvalues'), join(root, 'coefficients')] # If the MOs are already store in the HDF5 format return the path # to them and skip the calculation if search_data_in_hdf5(path_hdf5, hdf5_orb_path): logger.info("point_{} has already been calculated".format(k)) orbitals.append(hdf5_orb_path) else: logger.info("point_{} has been scheduled".format(k)) # Path to I/O files point_dir = folders[j] job_files = create_file_names(point_dir, k) job_name = 'point_{}'.format(k) # Compute the MOs and return a new guess promise_qm = compute_orbitals(guess_job, package_name, project_name, path_hdf5, settings_main, settings_guess, package_config, calc_new_wf_guess_on_points, point_dir, job_files, k, gs) # Check if the job finishes succesfully promise_qm = schedule_check(promise_qm, job_name, package_name, project_name, path_hdf5, settings_main, settings_guess, package_config, point_dir, job_files, k, gs, ignore_warnings=ignore_warnings) # Store the computation path_MOs = store_in_hdf5(project_name, path_hdf5, promise_qm, hdf5_orb_path, job_name) guess_job = promise_qm orbitals.append(path_MOs) return gather(*orbitals)
return j def error_filter(xcptn): if isinstance(xcptn, subprocess.CalledProcessError): return xcptn.stderr else: return None if __name__ == "__main__": parser = argparse.ArgumentParser( description="SOBA: Run a non-directional exclusion graph job.") parser.add_argument( '-j', dest='n_threads', type=int, default=1, help='number of threads to run simultaneously.') parser.add_argument( '-dumb', default=False, action='store_true', help='print info without special term codes.') parser.add_argument( 'target', type=str, help='a JSON file specifying the graph.') args = parser.parse_args(sys.argv[1:]) input = json.load(open(args.target, 'r')) jobs = [make_job(td['command'], td['task'], td['exclude']) for td in input] wf = noodles.gather(*jobs) with SimpleDisplay(error_filter) as display: run(wf, display=display, n_threads=args.n_threads)
def my_sum(a, buildin_sum=sum): return buildin_sum(a) # a bit more complicated example # ------------------------------- r1 = add(1, 1) r2 = sub(3, r1) def foo(a, b, c): return mul(add(a, b), c) multiples = [foo(i, r2, r1) for i in range(6)] r5 = my_sum(gather(*multiples)) # draw_workflow("graph-example2.svg", r5) with DumbDisplay() as display: # answer = run_logging(r5, 4, display) answer = run_parallel_opt(r5, 4, serial.base, "cache.json", display=display, cache_all=True) print("The answer is: {0}".format(answer))
# Get the result with the maximum energy apprTS = select_max(pesscan, 'energy') # Calculate the DFTB hessian DFTBfreq = dftb(templates.freq.overlay(settings), apprTS.molecule, job_name=name + "_DFTBfreq") # Run the TS optimization, using the initial hession from DFTB t = Settings() t.specific.adf.geometry.inithess = DFTBfreq.kf.path TS = adf(templates.ts.overlay(settings).overlay(t), DFTBfreq.molecule, job_name=name + "_TS") # Perform a freq calculation TSfreq = adf(templates.freq.overlay(settings), TS.molecule, job_name=name + "_freq") # Add the jobs to the job list job_list.append(gather(r1job, r2job, pjob, TSfreq, TS.optcycles)) # Finalize and draw workflow wf = gather(*job_list) draw_workflow("wf.svg", wf._workflow) # Actual execution of the jobs results = run(wf, n_processes=1) # Extract table from results table = {} for r1result, r2result, presult, tsresult, optcycles in results: # Retrieve the molecular coordinates mol = tsresult.molecule d1 = bond1.get_current_value(mol) d2 = bond2.get_current_value(mol)
# systematically generate list of names consisting of the 3 atoms # that vary in the series of reactions # e.g. "CNC", "CNN", etc. reaction_names = set() for a1 in ('C', 'N'): for a3 in ('C', 'N', 'O'): name = a1 + 'N' + a3 reaction_names.add(name) print(name) # generate all jobs job_list = [] for name in reaction_names: reactant = calc_reactant(name) product, adf_freq = calc_productAndTS(name) job_list.append(gather(reactant, product, adf_freq)) # Need also the energy of ethene ethene = rdkitTools.smiles2rdkit('C=C') E_ethene_job = adf(templates.geometry.overlay(settings), ethene, job_name="ethene").energy # finalize and draw workflow wf = gather(E_ethene_job, gather(*job_list)) draw_workflow("wf.svg", wf._workflow) # Actual execution of the jobs E_ethene, results = run(wf, n_processes=2)
@schedule def mul(a, b): return a*b @schedule def my_sum(a, buildin_sum=sum): return buildin_sum(a) # a bit more complicated example # ------------------------------- r1 = add(1, 1) r2 = sub(3, r1) def foo(a, b, c): return mul(add(a, b), c) multiples = [foo(i, r2, r1) for i in range(6)] r5 = my_sum(gather(*multiples)) draw_workflow("graph-example2.svg", r5) answer = run_parallel(r5, 4) print("The answer is: {0}".format(answer))
def __init__(self, result, mol_list): self.result = result self.mol_list = gather(*mol_list)
result = json.loads(p.stdout) return result # , p.stderr def error_filter(xcptn): if isinstance(xcptn, subprocess.CalledProcessError): return xcptn.stderr else: return None if __name__ == '__main__': command = Command('eā»Scatter', './escat', 'sp', '-no-png', '-machine', depth='-n', multiplicity='-m', scaling='-x', ball_size='-s', hilbert='-H', random='-R') sizes = [i * 0.05 for i in range(20)] a = command(depth=10, multiplicity=3, scaling=0.5, ball_size=0.01, hilbert=True) b = command(depth=10, multiplicity=3, scaling=0.5, ball_size=0.01, random=True) work = noodles.gather(a, b) with SimpleDisplay(error_filter) as display: result = noodles.run_logging(work, 1, display) for line in result: print(json.dumps(line, indent=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))
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)
# systematically generate list of names consisting of the 3 atoms that vary in # the series of reactions # e.g. "CNC", "CNN", etc. reaction_names = set() for a1 in ('C', 'N'): for a3 in ('C', 'N', 'O'): name = a1 + 'N' + a3 reaction_names.add(name) print(name) # generate all jobs job_list = [] for name in reaction_names: reactant = calc_reactant(name) product, adf_freq = calc_productAndTS(name) job_list.append(gather(reactant, product, adf_freq)) # Need also the energy of ethene acetylene = rdkitTools.smiles2plams('C#C') E_acetylene_job = adf(templates.geometry.overlay(settings), acetylene, job_name="acetylene").energy # Actual execution of the jobs E_acetylene, results = run(gather(E_acetylene_job, gather(*job_list)), n_processes=1) def bond_distance(r1, r2): return sqrt(sum((x - y) ** 2 for x, y in zip(r1, r2))) # extract table from results
def calculate_mos(config: dict) -> list: """ Look for the MO in the HDF5 file if they do not exists calculate them by splitting the jobs in batches given by the ``restart_chunk`` variables. Only the first job is calculated from scratch while the rest of the batch uses as guess the wave function of the first calculation in the batch. The config dict contains: :param geometries: list of molecular geometries :param project_name: Name of the project used as root path for storing data in HDF5. :param path_hdf5: Path to the HDF5 file that contains the numerical results. :param folders: path to the directories containing the MO outputs :param settings_main: Settings for the job to run. :param calc_new_wf_guess_on_points: Calculate a new Wave function guess in each of the geometries indicated. By Default only an initial guess is computed. :param enumerate_from: Number from where to start enumerating the folders create for each point in the MD :returns: path to nodes in the HDF5 file to MO energies and MO coefficients. """ # Read Cell parameters file general = config['cp2k_general_settings'] file_cell_parameters = general["file_cell_parameters"] if file_cell_parameters is not None: array_cell_parameters = read_cell_parameters_as_array( file_cell_parameters)[1] # First calculation has no initial guess # calculate the rest of the jobs using the previous point as initial guess orbitals = [] # list to the nodes in the HDF5 containing the MOs energies = [] guess_job = None for j, gs in enumerate(config.geometries): # number of the point with respect to all the trajectory k = j + config.enumerate_from # dictionary containing the information of the j-th job dict_input = defaultdict(lambda: None) dict_input["geometry"] = gs dict_input["k"] = k # Path where the MOs will be store in the HDF5 root = join(config.project_name, f'point_{k}', config.package_name, 'mo') dict_input["node_MOs"] = [ join(root, 'eigenvalues'), join(root, 'coefficients') ] dict_input["node_energy"] = join(root, 'energy') # If the MOs are already store in the HDF5 format return the path # to them and skip the calculation if is_data_in_hdf5(config.path_hdf5, dict_input["node_MOs"]): logger.info(f"point_{k} has already been calculated") orbitals.append(dict_input["node_MOs"]) else: logger.info(f"point_{k} has been scheduled") # Add cell parameters from file if given if file_cell_parameters is not None: adjust_cell_parameters(general, array_cell_parameters, j) # Path to I/O files dict_input["point_dir"] = config.folders[j] dict_input["job_files"] = create_file_names( dict_input["point_dir"], k) dict_input["job_name"] = f'point_{k}' # Compute the MOs and return a new guess promise_qm = compute_orbitals(config, dict_input, guess_job) # Check if the job finishes succesfully promise_qm = schedule_check(promise_qm, config, dict_input) # Store the computation orbitals.append(store_MOs(config, dict_input, promise_qm)) energies.append(store_enery(config, dict_input, promise_qm)) guess_job = promise_qm return gather(gather(*orbitals), gather(*energies))
def test_empty_gather(): d = noodles.gather() result = run_single(d) assert result == []
exec(option) for key, val in list(inputKeys.items()): if key == "complex_EXTRA": for option in inputKeys["complex_EXTRA"]: exec(option) job_list = [] for key, val in list(inputKeys.items()): if key == "r1path": ircFrags = GetFragmentList(val["r1path"], [inputKeys["r1fragment"]])[0] r1_mol = ircFrags["frag1"] r1 = adf(templates.geometry.overlay(settings_R1), r1_mol, job_name="r1") job_list.append(gather(r1)) for key, val in list(inputKeys.items()): if key == "r2path": ircFrags = GetFragmentList(val["r2path"], [inputKeys["r2fragment"]])[0] r2_mol = ircFrags["frag1"] r2 = adf(templates.geometry.overlay(settings_R2), r2_mol, job_name="r2") job_list.append(gather(r2)) for key, val in list(inputKeys.items()): if key == "rcpath": ircFrags = GetFragmentList(val["rcpath"], [inputKeys["rcfragment"]])[0] rc_mol = ircFrags["frag1"] rc = adf(templates.geometry.overlay(settings_RC), rc_mol, job_name="rc")
plams.init() # User Defined imports from qmworks.packages.SCM import dftb, adf # from qmworks.components import adffragmentsjob rdmol = Chem.MolFromPDBFile('Dialanine.pdb') supermol = rdopp.add_prot_Hs(rdmol) # settings = Settings () # settings.functional = 'bp86' # # settings.basis = 'DZP' # settings.specific.adf.basis.core = 'Large' # supermolecule calculation # supermol_job = adf(templates.singlepoint.overlay(settings), supermol, job_name = 'supermol_singlepoint') supermol_job = dftb(templates.singlepoint, supermol, job_name = 'supermol_singlepoint') # supermol_dipole = supermol_results.get_dipole_vector() #frags,caps = rdkitTools.partition_protein(supermol, cap=None) frags, caps = rdopp.partition_protein(supermol, cap=None) # mfcc_job = mfcc(adf, frags, caps, settings) mfcc_job = mfcc(dftb, frags, caps) supermol_result, mfcc_result = run(gather(supermol_job, mfcc_job)) print(supermol_result.dipole) print(mfcc_result.dipole)
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 gather(): return noodles.gather(*[add(x, x) for x in range(10)])
def empty_gather(): return noodles.gather()
for s1 in ('C', 'N', 'O'): n1 = rdkitTools.modify_atom(cnc_ts, 0, s1) for s2 in ('N', 'O', 'S'): n2 = rdkitTools.modify_atom(n1, 1, s2) for s3 in ('C', 'N', 'O'): n3 = rdkitTools.modify_atom(n2, 2, s3) name = s1 + '-' + s2 + '-' + s3 n3.properties.name = name dftb_freq = dftb(templates.freq.overlay(settings), n3, job_name=name + "_dftb_freq") t = Settings() t.specific.adf.geometry.inithess = dftb_freq.archive.path job_list.append(adf(templates.ts.overlay(settings).overlay(t), n3, job_name=name + "_ts")) wf = gather(*job_list) # Actual execution of the jobs results = run(wf, n_processes=1) def bond_distance(r1, r2): return sqrt(sum((x - y) ** 2 for x, y in zip(r1, r2))) # extract table from results print("System Bond1 Bond2") for TS in results: # Retrieve the molecular coordinates mol = TS.molecule d1 = bond_distance(mol.atoms[0].coords, mol.atoms[4].coords)
def calculate_mos(config: dict) -> list: """ Look for the MO in the HDF5 file if they do not exists calculate them by splitting the jobs in batches given by the ``restart_chunk`` variables. Only the first job is calculated from scratch while the rest of the batch uses as guess the wave function of the first calculation in the batch. The config dict contains: :param geometries: list of molecular geometries :param project_name: Name of the project used as root path for storing data in HDF5. :param path_hdf5: Path to the HDF5 file that contains the numerical results. :param folders: path to the directories containing the MO outputs :param settings_main: Settings for the job to run. :param calc_new_wf_guess_on_points: Calculate a new Wave function guess in each of the geometries indicated. By Default only an initial guess is computed. :param enumerate_from: Number from where to start enumerating the folders create for each point in the MD :returns: path to nodes in the HDF5 file to MO energies and MO coefficients. """ # Read Cell parameters file general = config['cp2k_general_settings'] file_cell_parameters = general["file_cell_parameters"] if file_cell_parameters is not None: array_cell_parameters = read_cell_parameters_as_array(file_cell_parameters)[1] # First calculation has no initial guess # calculate the rest of the jobs using the previous point as initial guess orbitals = [] # list to the nodes in the HDF5 containing the MOs energies = [] guess_job = None for j, gs in enumerate(config.geometries): # number of the point with respect to all the trajectory k = j + config.enumerate_from # dictionary containing the information of the j-th job dict_input = defaultdict(lambda: None) dict_input["geometry"] = gs dict_input["k"] = k # Path where the MOs will be store in the HDF5 root = join(config.project_name, 'point_{}'.format(k), config.package_name, 'mo') dict_input["node_MOs"] = [join(root, 'eigenvalues'), join(root, 'coefficients')] dict_input["node_energy"] = join(root, 'energy') # If the MOs are already store in the HDF5 format return the path # to them and skip the calculation if is_data_in_hdf5(config.path_hdf5, dict_input["node_MOs"]): logger.info("point_{} has already been calculated".format(k)) orbitals.append(dict_input["node_MOs"]) else: logger.info("point_{} has been scheduled".format(k)) # Add cell parameters from file if given if file_cell_parameters is not None: adjust_cell_parameters(general, array_cell_parameters, j) # Path to I/O files dict_input["point_dir"] = config.folders[j] dict_input["job_files"] = create_file_names(dict_input["point_dir"], k) dict_input["job_name"] = 'point_{}'.format(k) # Compute the MOs and return a new guess promise_qm = compute_orbitals(config, dict_input, guess_job) # Check if the job finishes succesfully promise_qm = schedule_check(promise_qm, config, dict_input) # Store the computation orbitals.append(store_MOs(config, dict_input, promise_qm)) energies.append(store_enery(config, dict_input, promise_qm)) guess_job = promise_qm return gather(gather(*orbitals), gather(*energies))
def unguarded_iteration(): a = noodles.delay((1, 2, 3)) b, c, d = a return noodles.gather(d, c, b)
job_list = [] # Loop over all reactions for name, r1_smiles, r2_smiles, p_smiles in reactions: # Prepare reactant1 job r1_mol = molkit.from_smiles(r1_smiles) r1_dftb = dftb(templates.geometry.overlay(settings), r1_mol, job_name=name + "_r1_DFTB") r1 = adf(templates.geometry.overlay(settings), r1_dftb.molecule, job_name=name + "_r1") r1_freq = adf(templates.freq.overlay(settings), r1.molecule, job_name=name + "_r1_freq") # Prepare reactant2 job r2s_mol = molkit.from_smiles(r2_smiles, nconfs=10, forcefield='mmff', rms=0.1) r2s_dftb = [dftb(templates.geometry.overlay(settings), r2_mol, job_name=name + "_r2_DFTB") for r2_mol in r2s_mol] r2_dftb = select_min(gather(*r2s_dftb), 'energy') r2 = adf(templates.geometry.overlay(settings), r2_dftb.molecule, job_name=name + "_r2") r2_freq = adf(templates.freq.overlay(settings), r2.molecule, job_name=name + "_r2_freq") # Prepare product job ps_mol = molkit.from_smiles(p_smiles, nconfs=10, forcefield='mmff', name=name, rms=0.1) ps_dftb = [dftb(templates.geometry.overlay(settings), p_mol, job_name=name + "_ps_DFTB") for p_mol in ps_mol] p_dftb = select_min(gather(*ps_dftb), 'energy') p = adf(templates.geometry.overlay(settings), p_dftb.molecule, job_name=name + "_p") p_freq = adf(templates.freq.overlay(settings), p.molecule, job_name=name + "_p_freq") # Prepare scan pes_jobs = [] for d in range(6): consset = Settings() consset.constraint.update(bond1.get_settings(2.0 + d * 0.1))
def calculate_mos(config: DictConfig) -> List[str]: """Look for the MO in the HDF5 file and compute them if they are not present. The orbitals are computed by splitting the jobs in batches given by the ``restart_chunk`` variables. Only the first job is calculated from scratch while the rest of the batch uses as guess the wave function of the first calculation inthe batch. The config dict contains: * geometries: list of molecular geometries * project_name: Name of the project used as root path for storing data in HDF5. * path_hdf5: Path to the HDF5 file that contains the numerical results. * folders: path to the directories containing the MO outputs * settings_main: Settings for the job to run. * calc_new_wf_guess_on_points: Calculate a new Wave function guess in each of the geometries indicated. By Default only an initial guess is computed. * enumerate_from: Number from where to start enumerating the folders create for each point in the MD Returns ------- paths to the datasets in the HDF5 file containging both the MO energies and MO coefficients """ # Read Cell parameters file general = config['cp2k_general_settings'] file_cell_parameters = general["file_cell_parameters"] if file_cell_parameters is not None: array_cell_parameters = read_cell_parameters_as_array(file_cell_parameters)[ 1] # First calculation has no initial guess # calculate the rest of the jobs using the previous point as initial guess orbitals = [] # list to the nodes in the HDF5 containing the MOs energies = [] guess_job = None # orbital type is either an empty string for restricted calculation # or alpha/beta for unrestricted calculations orbitals_type = config.orbitals_type for j, gs in enumerate(config.geometries): # number of the point with respect to all the trajectory k = j + config.enumerate_from # dictionary containing the information of the j-th job dict_input = defaultdict(lambda: None) # type: DefaultDict[str, Any] dict_input["geometry"] = gs dict_input["k"] = k # Path where the MOs will be store in the HDF5 dict_input["node_MOs"] = [ join(orbitals_type, "eigenvalues", f"point_{k}"), join(orbitals_type, "coefficients", f"point_{k}")] dict_input["node_energy"] = join(orbitals_type, "energy", f"point_{k}") # If the MOs are already store in the HDF5 format return the path # to them and skip the calculation if config["compute_orbitals"]: predicate = dict_input["node_MOs"] else: predicate = dict_input["node_energy"] if is_data_in_hdf5(config.path_hdf5, predicate): logger.info(f"point_{k} has already been calculated") orbitals.append(dict_input["node_MOs"]) else: logger.info(f"point_{k} has been scheduled") # Add cell parameters from file if given if file_cell_parameters is not None: adjust_cell_parameters(general, array_cell_parameters, j) # Path to I/O files dict_input["point_dir"] = config.folders[j] dict_input["job_files"] = create_file_names( dict_input["point_dir"], k) dict_input["job_name"] = f'point_{k}' # Compute the MOs and return a new guess promise_qm = compute_orbitals(config, dict_input, guess_job) # Check if the job finishes succesfully promise_qm = schedule_check(promise_qm, config, dict_input) # Store the computation if config["compute_orbitals"]: orbitals.append(store_molecular_orbitals(config, dict_input, promise_qm)) else: orbitals.append(None) energies.append(store_enery(config, dict_input, promise_qm)) guess_job = promise_qm return gather(gather(*orbitals), gather(*energies))
def test_gather(): d = noodles.gather(*[add(x, x) for x in range(10)]) result = run_single(d) assert result == list(range(0, 20, 2))
def test_42(): A = add(1, 1) B = sub(3, A) multiples = [mul(add(i, B), A) for i in range(6)] return accumulate(noodles.gather(*multiples))
# Settings for ADF SAOP single point calculation s = Settings() s.basis = 'DZP' s.specific.adf.basis.core = None s.specific.adf.xc.model = 'saop' s.specific.adf.scf.converge = 1e-6 s.specific.adf.symmetry = 'nosym' # single point calculations using the SAOP functional singlepoints = [ adf(s, mol, job_name='adf_{}'.format(name)) for name, mol in optimized_mols.items() ] # Filter results with H**O-LUMO gap lower than 3 eV candidates = filter_homo_lumo_lower_than(gather(*singlepoints), 3) # Optimize the selected candidates inp = templates.geometry inp.functional = 'pbe' inp.basis = 'DZP' inp.specific.adf.scf.converge = 1e-6 inp.specific.adf.symmetry = 'nosym' # Optimize only the filter candidates opt_jobs = iterate_over_jobs(candidates, inp, prefix='pbe') # Single point TD-DFT calculations s.specific.adf.excitations.allowed = '' s.specific.adf.excitations.lowest = 10
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)
command = Command('eā»Scatter', './escat', 'sp', '-no-png', '-machine', depth='-n', multiplicity='-m', scaling='-x', ball_size='-s', hilbert='-H', random='-R') sizes = [i * 0.05 for i in range(20)] a = command(depth=10, multiplicity=3, scaling=0.5, ball_size=0.01, hilbert=True) b = command(depth=10, multiplicity=3, scaling=0.5, ball_size=0.01, random=True) work = noodles.gather(a, b) with SimpleDisplay(error_filter) as display: result = noodles.run_logging(work, 1, display) for line in result: print(json.dumps(line, indent=2))
for a1 in ('C', 'N', 'O'): for a2 in ('N', 'O', 'S'): for a3 in ('C', 'N', 'O'): name = a1 + a2 + a3 reverse = a3 + a2 + a1 if reverse in reaction_names: # skip duplicates continue reaction_names.add(name) print(name) # generate all jobs job_list = [] for name in reaction_names: reactant = calc_reactant(name) product, adf_freq = calc_productAndTS(name) job_list.append(gather(reactant, product, adf_freq)) # Need also the energy of ethene ethene = rdkitTools.smiles2plams('C=C') E_ethene_job = adf(templates.geometry.overlay(settings), ethene, job_name="ethene").energy # Actual execution of the jobs E_ethene, results = run(gather(E_ethene_job, gather(*job_list)), n_processes=1) def bond_distance(r1, r2): return sqrt(sum((x - y)**2 for x, y in zip(r1, r2)))