def get_omega_xia(config: dict, dict_input: dict): """ Search for the multipole_matrices, Omega and xia values in the HDF5, if they are not available compute and store them. """ tddft = config.tddft.lower() def compute_omega_xia(): if tddft == 'sing_orb': return compute_sing_orb(dict_input) else: return compute_std_aproximation(config, dict_input) # search data in HDF5 root = join(config.project_name, 'omega_xia', tddft, 'point_{}'.format(dict_input.i + config.enumerate_from)) paths_omega_xia = [join(root, x) for x in ("omega", "xia")] if is_data_in_hdf5(config.path_hdf5, paths_omega_xia): return tuple(retrieve_hdf5_data(config.path_hdf5, paths_omega_xia)) else: omega, xia = compute_omega_xia() store_arrays_in_hdf5(config.path_hdf5, paths_omega_xia[0], omega, dtype=omega.dtype) store_arrays_in_hdf5(config.path_hdf5, paths_omega_xia[1], xia, dtype=xia.dtype) return omega, xia
def get_omega_xia(config: dict, dict_input: dict): """ Search for the multipole_matrices, Omega and xia values in the HDF5, if they are not available compute and store them. """ tddft = config.tddft.lower() def compute_omega_xia(): if tddft == 'sing_orb': return compute_sing_orb(dict_input) else: return compute_std_aproximation(config, dict_input) # search data in HDF5 root = join(config.project_name, 'omega_xia', tddft, 'point_{}'.format(dict_input.i + config.enumerate_from)) paths_omega_xia = [join(root, x) for x in ("omega", "xia")] if is_data_in_hdf5(config.path_hdf5, paths_omega_xia): return tuple(retrieve_hdf5_data(config.path_hdf5, paths_omega_xia)) else: omega, xia = compute_omega_xia() store_arrays_in_hdf5(config.path_hdf5, paths_omega_xia[0], omega, dtype=omega.dtype) store_arrays_in_hdf5(config.path_hdf5, paths_omega_xia[1], xia, dtype=xia.dtype) return omega, xia
def calculate_couplings(config: dict, i: int, fixed_phase_overlaps: Tensor3D) -> str: """ Search for the ith Coupling in the HDF5, if it is not available compute it using the 3 points approximation and store it in the HDF5 """ # time in atomic units dt_au = config.dt * femtosec2au # Path were the couplinp is store k = i + config.enumerate_from path = join(config.project_name, 'coupling_{}'.format(k)) # Skip the computation if the coupling is already done if is_data_in_hdf5(config.path_hdf5, path): logger.info("Coupling: {} has already been calculated".format(path)) return path else: logger.info("Computing coupling: {}".format(path)) if config.algorithm == 'levine': # Extract the overlap matrices involved in the coupling computation sji_t0 = fixed_phase_overlaps[i] # Compute the couplings with the phase corrected overlaps couplings = config["fun_coupling"](dt_au, sji_t0, sji_t0.transpose()) elif config.algorithm == '3points': sji_t0, sji_t1 = fixed_phase_overlaps[i: i + 2] couplings = config["fun_coupling"](dt_au, sji_t0, sji_t0.transpose(), sji_t1, sji_t1.transpose()) # Store the Coupling in the HDF5 store_arrays_in_hdf5(config.path_hdf5, path, couplings) return path
def compute_fragment_overlap( path_hdf5: str, path_overlap: str, fragment_atoms: List, path_mos: str, indices_fragment_mos: Vector, dictCGFs: Dict, trans_mtx: Matrix) -> str: """ Compute the overlap matrix only for those atoms included in the fragment """ if not search_data_in_hdf5(path_hdf5, path_overlap): logger.info("Computing overlap:{}".format(path_overlap)) # Compute the overlap in the atomic basis dim_cart = trans_mtx.shape[1] overlap_AO = triang2mtx( calcMtxOverlapP(fragment_atoms, dictCGFs), dim_cart) # Read all the molecular orbital coefficients coefficients = retrieve_hdf5_data(path_hdf5, path_mos[1]) # Number of Orbitals stored in the HDF5 dim_y = coefficients.shape[1] # Extract the coefficients belonging to the fragment dim_x = indices_fragment_mos.size # Extract the MO Coefficients belonging to the fragment x_range = np.repeat(indices_fragment_mos, dim_y) y_range = np.tile(np.arange(dim_y), dim_x) fragment_coefficients = coefficients[x_range, y_range].reshape(dim_x, dim_y) # Compute the overlap in spherical coordinates overlap_spherical = calculate_spherical_overlap( trans_mtx, overlap_AO, fragment_coefficients, fragment_coefficients) store_arrays_in_hdf5(path_hdf5, path_overlap, overlap_spherical) else: logger.info("overlap:{} already on HDF5".format(path_overlap)) return path_overlap
def calculate_couplings(fun_coupling: Callable, algorithm: str, i: int, project_name: str, fixed_phase_overlaps: Tensor3D, path_hdf5: str, enumerate_from: int, dt_au: float) -> str: """ Search for the ith Coupling in the HDF5, if it is not available compute it using the 3 points approximation. """ # Path were the couplinp is store k = i + enumerate_from path = join(project_name, 'coupling_{}'.format(k)) # Skip the computation if the coupling is already done if search_data_in_hdf5(path_hdf5, path): logger.info("Coupling: {} has already been calculated".format(path)) return path else: logger.info("Computing coupling: {}".format(path)) if algorithm == 'levine': # Extract the overlap matrices involved in the coupling computation sji_t0 = fixed_phase_overlaps[i] # Compute the couplings with the phase corrected overlaps couplings = fun_coupling(dt_au, sji_t0, sji_t0.transpose()) elif algorithm == '3points': sji_t0, sji_t1 = fixed_phase_overlaps[i:i + 2] couplings = fun_coupling(dt_au, sji_t0, sji_t0.transpose(), sji_t1, sji_t1.transpose()) # Store the Coupling in the HDF5 store_arrays_in_hdf5(path_hdf5, path, couplings) return path
def calculate_couplings(config: dict, i: int, fixed_phase_overlaps: Tensor3D) -> str: """ Search for the ith Coupling in the HDF5, if it is not available compute it using the 3 points approximation and store it in the HDF5 """ # time in atomic units dt_au = config.dt * femtosec2au # Path were the couplinp is store k = i + config.enumerate_from path = join(config.project_name, f'coupling_{k}') # Skip the computation if the coupling is already done if is_data_in_hdf5(config.path_hdf5, path): logger.info(f"Coupling: {path} has already been calculated") return path else: logger.info(f"Computing coupling: {path}") if config.algorithm == 'levine': # Extract the overlap matrices involved in the coupling computation sji_t0 = fixed_phase_overlaps[i] # Compute the couplings with the phase corrected overlaps couplings = config["fun_coupling"]( dt_au, sji_t0, sji_t0.transpose()) elif config.algorithm == '3points': sji_t0, sji_t1 = fixed_phase_overlaps[i: i + 2] couplings = config["fun_coupling"](dt_au, sji_t0, sji_t0.transpose(), sji_t1, sji_t1.transpose()) # Store the Coupling in the HDF5 store_arrays_in_hdf5(config.path_hdf5, path, couplings) return path
def compute_the_fixed_phase_overlaps(paths_overlaps: List, path_hdf5: str, project_name: str, enumerate_from: int, nHOMO: int) -> Tuple: """ First track the unavoided crossings between Molecular orbitals and finally correct the phase for the whole trajectory. """ number_of_frames = len(paths_overlaps) # Pasth to the overlap matrices after the tracking # and phase correction roots = [ join(project_name, 'overlaps_{}'.format(i)) for i in range(enumerate_from, number_of_frames + enumerate_from) ] paths_corrected_overlaps = [join(r, 'mtx_sji_t0_corrected') for r in roots] # Paths inside the HDF5 to the array containing the tracking of the # unavoided crossings path_swaps = join(project_name, 'swaps') # Compute the corrected overlaps if not avaialable in the HDF5 if not search_data_in_hdf5(path_hdf5, paths_corrected_overlaps[0]): # Compute the dimension of the coupling matrix mtx_0 = retrieve_hdf5_data(path_hdf5, paths_overlaps[0]) _, dim = mtx_0.shape # Read all the Overlaps overlaps = np.stack( [retrieve_hdf5_data(path_hdf5, ps) for ps in paths_overlaps]) # Number of couplings to compute nCouplings = overlaps.shape[0] # Compute the unavoided crossing using the Overlap matrix # and correct the swaps between Molecular Orbitals logger.debug("Computing the Unavoided crossings, " "Tracking the crossings between MOs") overlaps, swaps = track_unavoided_crossings(overlaps, nHOMO) # Compute all the phases taking into account the unavoided crossings logger.debug("Computing the phases of the MOs") mtx_phases = compute_phases(overlaps, nCouplings, dim) # Fixed the phases of the whole set of overlap matrices fixed_phase_overlaps = correct_phases(overlaps, mtx_phases) # Store corrected overlaps in the HDF5 store_arrays_in_hdf5(path_hdf5, paths_corrected_overlaps, fixed_phase_overlaps) # Store the Swaps tracking the crossing store_arrays_in_hdf5(path_hdf5, path_swaps, swaps, dtype=np.int32) else: # Read the corrected overlaps and the swaps from the HDF5 fixed_phase_overlaps = np.stack( retrieve_hdf5_data(path_hdf5, paths_corrected_overlaps)) swaps = retrieve_hdf5_data(path_hdf5, path_swaps) return fixed_phase_overlaps, swaps
def lazy_overlaps(i: int, project_name: str, path_hdf5: str, dictCGFs: Dict, geometries: Tuple, mo_paths: List, hdf5_trans_mtx: str = None, enumerate_from: int = 0, nHOMO: int = None, couplings_range: Tuple = None) -> str: """ Calculate the 4 overlap matrix used to compute the subsequent couplings. The overlap matrices are computed using 3 consecutive set of MOs and 3 consecutive geometries( in atomic units), from a molecular dynamics. :param i: nth coupling calculation :param project_name: Name of the project to be executed. :paramter dictCGFS: Dictionary from Atomic Label to basis set :type dictCGFS: Dict String [CGF], CGF = ([Primitives], AngularMomentum), Primitive = (Coefficient, Exponent) :parameter geometries: molecular geometries stored as list of namedtuples. :type geometries: ([AtomXYZ], [AtomXYZ], [AtomXYZ]) :parameter mo_paths: List of paths to the MO in the HDF5 :param hdf5_trans_mtx: Path to the transformation matrix in the HDF5 :param enumerate_from: Number from where to start enumerating the folders create for each point in the MD :param nHOMO: index of the H**O orbital in the HDF5 :param couplings_range: range of Molecular orbitals used to compute the coupling. :returns: path to the Coupling inside the HDF5 """ # Path inside the HDF5 where the overlaps are stored root = join(project_name, 'overlaps_{}'.format(i + enumerate_from)) overlaps_paths_hdf5 = join(root, 'mtx_sji_t0') # If the Overlaps are not in the HDF5 file compute them if search_data_in_hdf5(path_hdf5, overlaps_paths_hdf5): logger.info("{} Overlaps are already in the HDF5".format(root)) else: # Read the Molecular orbitals from the HDF5 logger.info("Computing: {}".format(root)) # Paths to the MOs inside the HDF5 hdf5_mos_path = [mo_paths[i + j][1] for j in range(2)] # Partial application of the function computing the overlap overlaps = compute_overlaps_for_coupling(geometries, path_hdf5, hdf5_mos_path, dictCGFs, nHOMO, couplings_range, hdf5_trans_mtx) # Store the matrices in the HDF5 file store_arrays_in_hdf5(path_hdf5, overlaps_paths_hdf5, overlaps) return overlaps_paths_hdf5
def compute_the_fixed_phase_overlaps( paths_overlaps: List, path_hdf5: str, project_name: str, enumerate_from: int, nHOMO: int) -> Tuple: """ First track the unavoided crossings between Molecular orbitals and finally correct the phase for the whole trajectory. """ number_of_frames = len(paths_overlaps) # Pasth to the overlap matrices after the tracking # and phase correction roots = [join(project_name, 'overlaps_{}'.format(i)) for i in range(enumerate_from, number_of_frames + enumerate_from)] paths_corrected_overlaps = [join(r, 'mtx_sji_t0_corrected') for r in roots] # Paths inside the HDF5 to the array containing the tracking of the # unavoided crossings path_swaps = join(project_name, 'swaps') # Compute the corrected overlaps if not avaialable in the HDF5 if not is_data_in_hdf5(path_hdf5, paths_corrected_overlaps[0]): # Compute the dimension of the coupling matrix mtx_0 = retrieve_hdf5_data(path_hdf5, paths_overlaps[0]) _, dim = mtx_0.shape # Read all the Overlaps overlaps = np.stack([retrieve_hdf5_data(path_hdf5, ps) for ps in paths_overlaps]) # Number of couplings to compute nCouplings = overlaps.shape[0] # Compute the unavoided crossing using the Overlap matrix # and correct the swaps between Molecular Orbitals logger.debug("Computing the Unavoided crossings, " "Tracking the crossings between MOs") overlaps, swaps = track_unavoided_crossings(overlaps, nHOMO) # Compute all the phases taking into account the unavoided crossings logger.debug("Computing the phases of the MOs") mtx_phases = compute_phases(overlaps, nCouplings, dim) # Fixed the phases of the whole set of overlap matrices fixed_phase_overlaps = correct_phases(overlaps, mtx_phases) # Store corrected overlaps in the HDF5 store_arrays_in_hdf5(path_hdf5, paths_corrected_overlaps, fixed_phase_overlaps) # Store the Swaps tracking the crossing store_arrays_in_hdf5(path_hdf5, path_swaps, swaps, dtype=np.int32) else: # Read the corrected overlaps and the swaps from the HDF5 fixed_phase_overlaps = np.stack( retrieve_hdf5_data(path_hdf5, paths_corrected_overlaps)) swaps = retrieve_hdf5_data(path_hdf5, path_swaps) return fixed_phase_overlaps, swaps
def store_enery(config: dict, dict_input: dict, promise_qm: object) -> str: """ Store the total energy in the HDF5 file. """ store_arrays_in_hdf5(config.path_hdf5, dict_input['node_energy'], promise_qm.energy) logger.info( f"Total energy of point {dict_input['k']} is: {promise_qm.energy}") return dict_input["node_energy"]
def store_enery(config: dict, dict_input: dict, promise_qm: object) -> str: """ Store the total energy in the HDF5 file. """ store_arrays_in_hdf5( config.path_hdf5, dict_input['node_energy'], promise_qm.energy) logger.info("Total energy of point {} is: {}".format( dict_input['k'], promise_qm.energy)) return dict_input["node_energy"]
def test_cube(): """ Test the density compute to create a cube file. """ if not os.path.exists(scratch_path): os.makedirs(scratch_path) # Overlap matrix in cartesian coordinates basisname = "DZVP-MOLOPT-SR-GTH" # Read coordinates molecule = change_mol_units(readXYZ(path_xyz)) # String representation of the molecule geometries = split_file_geometries(path_xyz) try: shutil.copy(path_original_hdf5, path_test_hdf5) # Contracted Gauss functions dictCGFs = create_dict_CGFs(path_test_hdf5, basisname, molecule) dict_global_norms = compute_normalization_sphericals(dictCGFs) # Compute the transformation matrix and store it in the HDF5 with h5py.File(path_test_hdf5, 'r') as f5: transf_mtx = calc_transf_matrix( f5, molecule, basisname, dict_global_norms, 'cp2k') path_transf_mtx = join(project_name, 'trans_mtx') store_arrays_in_hdf5( path_test_hdf5, path_transf_mtx, transf_mtx) # voxel size and Number of steps grid_data = GridCube(0.300939, 80) rs = workflow_compute_cubes( 'cp2k', project_name, package_args, path_time_coeffs=None, grid_data=grid_data, guess_args=None, geometries=geometries, dictCGFs=dictCGFs, calc_new_wf_guess_on_points=[], path_hdf5=path_test_hdf5, enumerate_from=0, package_config=None, traj_folders=None, work_dir=scratch_path, basisname=basisname, hdf5_trans_mtx=path_transf_mtx, nHOMO=6, orbitals_range=(6, 6), ignore_warnings=False) xs = retrieve_hdf5_data(path_test_hdf5, rs)[0] np.save("grid_density", xs) finally: # Remove intermediate results shutil.rmtree(scratch_path)
def get_multipole_matrix(config: dict, inp: dict, multipole: str) -> Matrix: """ Retrieve the `multipole` number `i` from the trajectory. Otherwise compute it. """ root = join(config['project_name'], 'multipole', 'point_{}'.format(inp.i + config.enumerate_from)) path_hdf5 = config['path_hdf5'] path_multipole_hdf5 = join(root, multipole) matrix_multipole = search_multipole_in_hdf5(path_hdf5, path_multipole_hdf5, multipole) if matrix_multipole is None: matrix_multipole = compute_matrix_multipole(inp.mol, config, multipole) store_arrays_in_hdf5(path_hdf5, path_multipole_hdf5, matrix_multipole) return matrix_multipole
def get_multipole_matrix(config: dict, inp: dict, multipole: str) -> Matrix: """ Retrieve the `multipole` number `i` from the trajectory. Otherwise compute it. """ root = join(config['project_name'], 'multipole', f'point_{inp.i + config.enumerate_from}') path_hdf5 = config['path_hdf5'] path_multipole_hdf5 = join(root, multipole) matrix_multipole = search_multipole_in_hdf5( path_hdf5, path_multipole_hdf5, multipole) if matrix_multipole is None: matrix_multipole = compute_matrix_multipole(inp.mol, config, multipole) store_arrays_in_hdf5(path_hdf5, path_multipole_hdf5, matrix_multipole) return matrix_multipole
def get_multipole_matrix(i: int, mol: List, config: Dict, multipole: str) -> Matrix: """ Retrieve the `multipole` number `i` from the trajectory. Otherwise compute it. """ root = join(config['project_name'], 'multipole', 'point_{}'.format(i)) path_hdf5 = config['path_hdf5'] path_multipole_hdf5 = join(root, multipole) matrix_multipole = search_multipole_in_hdf5(path_hdf5, path_multipole_hdf5, multipole) if matrix_multipole is None: matrix_multipole = compute_matrix_multipole(mol, config, multipole) store_arrays_in_hdf5(path_hdf5, path_multipole_hdf5, matrix_multipole) return matrix_multipole
def single_machine_overlaps(config: dict, mo_paths_hdf5: list, i: int): """ Compute the overlaps in the CPUs avaialable on the local machine """ # Data to compute the overlaps pair_molecules = select_molecules(config, i) mo_paths = [mo_paths_hdf5[i + j][1] for j in range(2)] coefficients = read_overlap_data(config, mo_paths) # Compute the overlap overlaps = compute_overlaps_for_coupling( config, pair_molecules, coefficients) # Store the array in the HDF5 overlaps_paths_hdf5 = create_overlap_path(config, i) store_arrays_in_hdf5(config.path_hdf5, overlaps_paths_hdf5, overlaps) return overlaps_paths_hdf5
def single_machine_overlaps(config: dict, mo_paths_hdf5: list, i: int): """ Compute the overlaps in the CPUs avaialable on the local machine """ # Data to compute the overlaps pair_molecules = select_molecules(config, i) mo_paths = [mo_paths_hdf5[i + j][1] for j in range(2)] coefficients = read_overlap_data(config, mo_paths) # Compute the overlap overlaps = compute_overlaps_for_coupling( config, pair_molecules, coefficients) # Store the array in the HDF5 overlaps_paths_hdf5 = create_overlap_path(config, i) store_arrays_in_hdf5(config.path_hdf5, overlaps_paths_hdf5, overlaps) return overlaps_paths_hdf5
def calcOscillatorStrenghts(i: int, project_name: str, mo_paths_hdf5: str, dictCGFs: Dict, atoms: List, path_hdf5: str, hdf5_trans_mtx: str = None, initial_states: Vector = None, final_states: Matrix = None): """ Use the Molecular orbital Energies and Coefficients to compute the oscillator_strength. :param i: time frame :param project_name: Folder name where the computations are going to be stored. :param mo_paths_hdf5: Path to the MO coefficients and energies in the HDF5 file. :paramter dictCGFS: Dictionary from Atomic Label to basis set. :type dictCGFS: Dict String [CGF], CGF = ([Primitives], AngularMomentum), Primitive = (Coefficient, Exponent) :param atoms: Molecular geometry. :type atoms: [namedtuple("AtomXYZ", ("symbol", "xyz"))] :param path_hdf5: Path to the HDF5 file that contains the numerical results. :param hdf5_trans_mtx: path to the transformation matrix in the HDF5 file. :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]] """ # Energy and coefficients at time t es, coeffs = retrieve_hdf5_data(path_hdf5, mo_paths_hdf5[i]) # If the MO orbitals are given in Spherical Coordinates transform then to # Cartesian Coordinates. if hdf5_trans_mtx is not None: trans_mtx = retrieve_hdf5_data(path_hdf5, hdf5_trans_mtx) logger.info("Computing the oscillator strength at time: {}".format(i)) # Overlap matrix # Origin of the dipole rc = compute_center_of_mass(atoms) # Dipole matrix element in spherical coordinates path_dipole_matrices = join(project_name, 'point_{}'.format(i), 'dipole_matrices') if search_data_in_hdf5(path_hdf5, path_dipole_matrices): mtx_integrals_spher = retrieve_hdf5_data(path_hdf5, path_dipole_matrices) else: # Compute the Dipole matrices and store them in the HDF5 mtx_integrals_spher = calcDipoleCGFS(atoms, dictCGFs, rc, trans_mtx) store_arrays_in_hdf5(path_hdf5, path_dipole_matrices, mtx_integrals_spher) oscillators = [ compute_oscillator_strength(rc, atoms, dictCGFs, es, coeffs, mtx_integrals_spher, initialS, fs) for initialS, fs in zip(initial_states, final_states) ] return oscillators