Пример #1
0
def _get_heat_of_formation(spc_name, spc_dct, spc_mod, spc_locs, spc_mod_dct_i,
                           basis_dct, ref_enes, chn_basis_ene_dct, run_prefix,
                           save_prefix):
    """ get the heat of formation at  0 K
    """

    spc_basis, coeff_basis = basis_dct[spc_name]
    # Get the energies for the spc and its basis
    energy_missing, ene_basis = _check_for_reference_energies(
        spc_basis, chn_basis_ene_dct, spc_mod)
    if energy_missing:
        print('uh oh i messed things up')
    pf_filesystems = filesys.models.pf_filesys(spc_dct[spc_name],
                                               spc_mod_dct_i,
                                               run_prefix,
                                               save_prefix,
                                               saddle=False,
                                               spc_locs=spc_locs)
    ene_spc = ene.read_energy(spc_dct[spc_name],
                              pf_filesystems,
                              spc_mod_dct_i,
                              run_prefix,
                              read_ene=True,
                              read_zpe=True,
                              saddle=False)
    hf0k = thermfit.heatform.calc_hform_0k(ene_spc,
                                           ene_basis,
                                           spc_basis,
                                           coeff_basis,
                                           ref_set=ref_enes)
    return hf0k, chn_basis_ene_dct
Пример #2
0
    def _read_basis_energy(ich_name_dct,
                           spc_dct,
                           uni_refs_dct,
                           spc_model_dct_i,
                           run_prefix,
                           save_prefix,
                           ichs,
                           output_queue=None):

        h_basis_dct = {}
        print(f'Process {os.getpid()} reading energy for species: {ichs}')
        for ich in ichs:
            name = ich_name_dct[ich]
            if name in spc_dct:
                spc_dct_i = spc_dct[name]
                prname = name
            elif name in uni_refs_dct:
                spc_dct_i = uni_refs_dct[name]
                prname = name
            if 'ts' in name or 'TS' in name:
                reacs, prods = ich.split('PRODS')
                reacs = reacs.replace('REACS', '')
                reacs = reacs.split('REAC')
                prods = prods.split('PROD')
                reac_lbl = 'r0'
                if len(reacs) > 1:
                    reac_lbl += '+r1'
                prod_lbl = 'p0'
                if len(prods) > 1:
                    prod_lbl += '+p1'
                ioprinter.info_message(
                    f'Basis Reaction: {reac_lbl}={prod_lbl} 1 1 1 ')
                for i, reac in enumerate(reacs):
                    ioprinter.info_message(
                        f'r{i},{reac},{automol.inchi.smiles(reac)},1')
                for i, prod in enumerate(prods):
                    ioprinter.info_message(
                        f'p{i},{prod},{automol.inchi.smiles(prod)},1')
            ioprinter.debug_message('bases energies test:', ich, name)
            pf_filesystems = filesys.models.pf_filesys(
                spc_dct_i,
                spc_model_dct_i,
                run_prefix,
                save_prefix,
                saddle=('ts' in name or 'TS' in name),
                name=name)
            ioprinter.info_message(f'Calculating energy for basis {prname}...',
                                   newline=1)
            h_basis_dct[ich] = read_energy(spc_dct_i,
                                           pf_filesystems,
                                           spc_model_dct_i,
                                           run_prefix,
                                           read_ene=True,
                                           read_zpe=True,
                                           saddle='ts' in name or 'TS' in name)
        output_queue.put((h_basis_dct, ))
Пример #3
0
def enthalpy(spc_name, spc_dct, spc_dct_i, spc_mod_dct_i, model_dct,
             chn_basis_ene_dct, spc_array, locs, locs_path, cnf_fs, run_prefix,
             save_prefix):
    """ collect enthalpies
    """

    zrxn = spc_dct_i.get('zrxn')
    saddle = bool(zrxn)

    # print('spc_mod_dct_i', spc_mod_dct_i)
    pf_filesystems = filesys.models.pf_filesys(spc_dct_i,
                                               spc_mod_dct_i,
                                               run_prefix,
                                               save_prefix,
                                               name=spc_name,
                                               saddle=saddle,
                                               spc_locs=locs)
    # print(pf_filesystems)
    ene_abs = ene.read_energy(spc_dct_i,
                              pf_filesystems,
                              spc_mod_dct_i,
                              run_prefix,
                              conf=(locs, locs_path, cnf_fs),
                              read_ene=True,
                              read_zpe=True,
                              saddle=saddle)
    hf0k, _, chn_basis_ene_dct, hbasis = basis.enthalpy_calculation(
        spc_dct,
        spc_name,
        ene_abs,
        chn_basis_ene_dct,
        model_dct,
        spc_mod_dct_i,
        run_prefix,
        save_prefix,
        pforktp='pf',
        zrxn=zrxn)
    spc_basis, coeff_basis = hbasis[spc_name]
    coeff_array = []
    for spc_i in spc_basis:
        if spc_i not in spc_array:
            spc_array.append(spc_i)
    for spc_i in spc_array:
        if spc_i in spc_basis:
            coeff_array.append(coeff_basis[spc_basis.index(spc_i)])
        else:
            coeff_array.append(0)
    return ([locs_path, ene_abs, hf0k,
             *coeff_array], chn_basis_ene_dct, spc_array)
Пример #4
0
def basis_energy(spc_name,
                 spc_basis,
                 uni_refs_dct,
                 spc_dct,
                 spc_model_dct_i,
                 run_prefix,
                 save_prefix,
                 read_species=True):
    """ Reads the electronic and zero-point energies for a species and
        transition state and their constituent basis set.
    """
    def _read_basis_energy(ich_name_dct,
                           spc_dct,
                           uni_refs_dct,
                           spc_model_dct_i,
                           run_prefix,
                           save_prefix,
                           ichs,
                           output_queue=None):

        h_basis_dct = {}
        print(f'Process {os.getpid()} reading energy for species: {ichs}')
        for ich in ichs:
            name = ich_name_dct[ich]
            if name in spc_dct:
                spc_dct_i = spc_dct[name]
                prname = name
            elif name in uni_refs_dct:
                spc_dct_i = uni_refs_dct[name]
                prname = name
            if 'ts' in name or 'TS' in name:
                reacs, prods = ich.split('PRODS')
                reacs = reacs.replace('REACS', '')
                reacs = reacs.split('REAC')
                prods = prods.split('PROD')
                reac_lbl = 'r0'
                if len(reacs) > 1:
                    reac_lbl += '+r1'
                prod_lbl = 'p0'
                if len(prods) > 1:
                    prod_lbl += '+p1'
                ioprinter.info_message(
                    f'Basis Reaction: {reac_lbl}={prod_lbl} 1 1 1 ')
                for i, reac in enumerate(reacs):
                    ioprinter.info_message(
                        f'r{i},{reac},{automol.inchi.smiles(reac)},1')
                for i, prod in enumerate(prods):
                    ioprinter.info_message(
                        f'p{i},{prod},{automol.inchi.smiles(prod)},1')
            ioprinter.debug_message('bases energies test:', ich, name)
            pf_filesystems = filesys.models.pf_filesys(
                spc_dct_i,
                spc_model_dct_i,
                run_prefix,
                save_prefix,
                saddle=('ts' in name or 'TS' in name),
                name=name)
            ioprinter.info_message(f'Calculating energy for basis {prname}...',
                                   newline=1)
            h_basis_dct[ich] = read_energy(spc_dct_i,
                                           pf_filesystems,
                                           spc_model_dct_i,
                                           run_prefix,
                                           read_ene=True,
                                           read_zpe=True,
                                           saddle='ts' in name or 'TS' in name)
        output_queue.put((h_basis_dct, ))

    # Initialize ich name dct to noe
    ich_name_dct = {}
    for ich in spc_basis:
        if isinstance(ich, str):
            ich_name_dct[ich] = None
        else:
            ich_name_dct[_ich_key_name(ich)] = None

    # Get names of the basis species from the respective spc dcts
    for ich in spc_basis:
        for name in spc_dct:
            if name != 'global' and 'ts' not in name:
                if ich == spc_dct[name]['inchi']:
                    ich_name_dct[ich] = name
            elif name != 'global':
                if 'reacs' in spc_dct[name]:
                    if _ich_in_rxn(ich, spc_dct[name]):
                        ich_name_dct[_ich_key_name(ich)] = name
        for name in uni_refs_dct:
            if 'TS' in name:
                ioprinter.info_message(uni_refs_dct[name]['reacs'])
                if _ich_in_rxn(ich, uni_refs_dct[name]):
                    ich_name_dct[_ich_key_name(ich)] = name
            elif ich == uni_refs_dct[name]['inchi']:
                ich_name_dct[ich] = name

    # Check the ich_name_dct
    dct_incomplete = False
    for ich, name in ich_name_dct.items():
        if name is None:
            ioprinter.warning_message(f'{ich} not given in species.csv file')
            dct_incomplete = True
    if dct_incomplete:
        ioprinter.error_message('Job ending since basis species not specified')
        sys.exit()

    # Get the species energy
    if read_species:
        ioprinter.info_message(f'Calculating energy for species {spc_name}',
                               newline=1)
        pf_filesystems = filesys.models.pf_filesys(spc_dct[spc_name],
                                                   spc_model_dct_i,
                                                   run_prefix,
                                                   save_prefix,
                                                   saddle='ts' in spc_name,
                                                   name=spc_name)
        h_spc = read_energy(spc_dct[spc_name],
                            pf_filesystems,
                            spc_model_dct_i,
                            run_prefix,
                            read_ene=True,
                            read_zpe=True,
                            saddle='ts' in spc_name)
        if h_spc is None:
            ioprinter.error_message(f'No energy found for {spc_name}')
            sys.exit()
    else:
        h_spc = None

    # Get the energies of the bases
    h_basis = []
    ichs = [*ich_name_dct.keys()]
    args = (ich_name_dct, spc_dct, uni_refs_dct, spc_model_dct_i, run_prefix,
            save_prefix)
    h_basis_dct_lst = execute_function_in_parallel(_read_basis_energy,
                                                   ichs,
                                                   args,
                                                   nprocs=4)
    print('hbasis list', h_basis_dct_lst)
    for ich in ichs:
        for h_basis_dct in h_basis_dct_lst:
            if ich in h_basis_dct:
                h_basis.append(h_basis_dct[ich])
                break
    print(h_basis)
    # Check if all the energies found
    no_ene_cnt = 0
    for basis_ene, basis_name in zip(h_basis, ich_name_dct.values()):
        if basis_ene is None:
            ioprinter.warning_message(f'No energy found for {basis_name}')
            no_ene_cnt += 1
    if no_ene_cnt > 1:
        ioprinter.error_message('Not all energies found for the basis species')
        sys.exit()

    return h_spc, h_basis
Пример #5
0
def run_tsk(tsk, spc_dct, spc_name, thy_dct, proc_keyword_dct, pes_mod_dct_i,
            spc_mod_dct_i, run_prefix, save_prefix):
    """ run a proc tess task
    for generating a list of conformer or tau sampling geometries
    """

    # Print the head of the task
    ioprinter.output_task_header(tsk)
    ioprinter.obj('line_dash')
    ioprinter.output_keyword_list(proc_keyword_dct, thy_dct)

    # Setup csv data dictionary for specific task
    csv_data = util.set_csv_data(tsk)
    chn_basis_ene_dct = {}
    spc_array = []

    # print species
    ioprinter.obj('line_dash')
    ioprinter.info_message("Species: ", spc_name)

    # Heat of formation basis molecules and coefficients
    # is not conformer specific
    if 'coeffs' in tsk:
        thy_info = spc_mod_dct_i['geo'][1]
        filelabel = 'coeffs'
        filelabel += '_{}'.format(pes_mod_dct_i['thermfit']['ref_scheme'])
        filelabel += '.csv'
        label = spc_name
        basis_dct, _ = basis.prepare_refs(
            pes_mod_dct_i['thermfit']['ref_scheme'], spc_dct, (spc_name, ))
        # Get the basis info for the spc of interest
        spc_basis, coeff_basis = basis_dct[spc_name]
        coeff_array = []
        for spc_i in spc_basis:
            if spc_i not in spc_array:
                spc_array.append(spc_i)
        for spc_i in spc_array:
            if spc_i in spc_basis:
                coeff_array.append(coeff_basis[spc_basis.index(spc_i)])
            else:
                coeff_array.append(0)
        csv_data[label] = [*coeff_array]

    else:
        # unpack spc and level info
        spc_dct_i = spc_dct[spc_name]
        if proc_keyword_dct['geolvl']:
            thy_info = tinfo.from_dct(thy_dct.get(proc_keyword_dct['geolvl']))
        else:
            thy_info = spc_mod_dct_i['geo'][1]

            # Loop over conformers
        if proc_keyword_dct['geolvl']:
            _, rng_cnf_locs_lst, rng_cnf_locs_path = util.conformer_list(
                proc_keyword_dct, save_prefix, run_prefix, spc_dct_i, thy_dct)
            spc_mod_dct_i, pf_models = None, None
        else:
            ret = util.conformer_list_from_models(proc_keyword_dct,
                                                  save_prefix, run_prefix,
                                                  spc_dct_i, thy_dct,
                                                  spc_mod_dct_i, pf_models)
            _, rng_cnf_locs_lst, rng_cnf_locs_path = ret
        for locs, locs_path in zip(rng_cnf_locs_lst, rng_cnf_locs_path):

            label = spc_name + '_' + '_'.join(locs)
            _, cnf_fs = filesys.build_fs(run_prefix, save_prefix, 'CONFORMER')
            if 'freq' in tsk:

                filelabel = 'freq'
                if spc_mod_dct_i:
                    filelabel += '_m{}'.format(spc_mod_dct_i['harm'][0])
                else:
                    filelabel += '_{}'.format(proc_keyword_dct['geolvl'])
                filelabel += '.csv'

                if pf_models:
                    pf_filesystems = filesys.models.pf_filesys(spc_dct_i,
                                                               spc_mod_dct_i,
                                                               run_prefix,
                                                               save_prefix,
                                                               saddle=False)
                    ret = vib.full_vib_analysis(spc_dct_i,
                                                pf_filesystems,
                                                spc_mod_dct_i,
                                                run_prefix,
                                                zrxn=None)
                    freqs, _, tors_zpe, sfactor, torsfreqs, all_freqs = ret
                    csv_data['tfreq'][label] = torsfreqs
                    csv_data['allfreq'][label] = all_freqs
                    csv_data['scalefactor'][label] = [sfactor]
                else:
                    es_model = util.freq_es_levels(proc_keyword_dct)
                    spc_mod_dct_i = parser.model.pf_level_info(
                        es_model, thy_dct)
                    try:
                        freqs, _, zpe = vib.read_locs_harmonic_freqs(
                            cnf_fs, locs, run_prefix, zrxn=None)
                    except:
                        freqs = []
                        zpe = 0

                tors_zpe = 0.0
                spc_data = []
                zpe = tors_zpe + (sum(freqs) / 2.0) * phycon.WAVEN2EH
                if freqs and proc_keyword_dct['scale'] is not None:
                    freqs, zpe = vib.scale_frequencies(freqs,
                                                       tors_zpe,
                                                       spc_mod_dct_i,
                                                       scale_method='3c')
                spc_data = [locs_path, zpe, *freqs]
                csv_data['freq'][label] = spc_data
            elif 'geo' in tsk:

                filelabel = 'geo'
                if spc_mod_dct_i:
                    filelabel += '_{}'.format(spc_mod_dct_i['harm'])
                else:
                    filelabel += '_{}'.format(proc_keyword_dct['geolvl'])
                filelabel += '.txt'

                if cnf_fs[-1].file.geometry.exists(locs):
                    geo = cnf_fs[-1].file.geometry.read(locs)
                    energy = cnf_fs[-1].file.energy.read(locs)
                    comment = 'energy: {0:>15.10f}'.format(energy)
                    xyz_str = automol.geom.xyz_string(geo, comment=comment)
                else:
                    xyz_str = '\t -- Missing --'
                spc_data = '\n\nSPC: {}\tConf: {}\tPath: {}\n'.format(
                    spc_name, locs, locs_path) + xyz_str

                csv_data[label] = spc_data

            elif 'zma' in tsk:

                filelabel = 'zmat'
                if spc_mod_dct_i:
                    filelabel += '_{}'.format(spc_mod_dct_i['harm'])
                else:
                    filelabel += '_{}'.format(proc_keyword_dct['geolvl'])
                filelabel += '.txt'

                geo = cnf_fs[-1].file.geometry.read(locs)
                zma = automol.geom.zmatrix(geo)
                energy = cnf_fs[-1].file.energy.read(locs)
                comment = 'energy: {0:>15.10f}\n'.format(energy)
                zma_str = automol.zmat.string(zma)
                spc_data = '\n\nSPC: {}\tConf: {}\tPath: {}\n'.format(
                    spc_name, locs, locs_path) + comment + zma_str
                csv_data[label] = spc_data

            elif 'ene' in tsk:

                filelabel = 'ene'
                if spc_mod_dct_i:
                    filelabel += '_{}'.format(spc_mod_dct_i['harm'])
                    filelabel += '_{}'.format(spc_mod_dct_i['ene'])
                else:
                    filelabel += '_{}'.format(proc_keyword_dct['geolvl'])
                    filelabel += '_{}'.format(proc_keyword_dct['proplvl'])
                filelabel += '.csv'

                energy = None
                if spc_mod_dct_i:
                    pf_filesystems = filesys.models.pf_filesys(spc_dct_i,
                                                               spc_mod_dct_i,
                                                               run_prefix,
                                                               save_prefix,
                                                               saddle=False)
                    energy = ene.electronic_energy(spc_dct_i,
                                                   pf_filesystems,
                                                   spc_mod_dct_i,
                                                   conf=(locs, locs_path,
                                                         cnf_fs))
                else:
                    spc_info = sinfo.from_dct(spc_dct_i)
                    thy_info = tinfo.from_dct(
                        thy_dct.get(proc_keyword_dct['proplvl']))
                    mod_thy_info = tinfo.modify_orb_label(thy_info, spc_info)
                    sp_save_fs = autofile.fs.single_point(locs_path)
                    sp_save_fs[-1].create(mod_thy_info[1:4])
                    # Read the energy
                    sp_path = sp_save_fs[-1].path(mod_thy_info[1:4])
                    if os.path.exists(sp_path):
                        if sp_save_fs[-1].file.energy.exists(
                                mod_thy_info[1:4]):
                            ioprinter.reading('Energy', sp_path)
                            energy = sp_save_fs[-1].file.energy.read(
                                mod_thy_info[1:4])
                csv_data[label] = [locs_path, energy]

            elif 'enthalpy' in tsk:
                filelabel = 'enthalpy'
                if spc_mod_dct_i:
                    filelabel += '_{}'.format(spc_mod_dct_i['harm'])
                    filelabel += '_{}'.format(spc_mod_dct_i['ene'])
                else:
                    filelabel += '_{}'.format(proc_keyword_dct['geolvl'])
                    filelabel += '_{}'.format(proc_keyword_dct['proplvl'])
                filelabel = '.csv'

                energy = None
                pf_filesystems = filesys.models.pf_filesys(spc_dct_i,
                                                           spc_mod_dct_i,
                                                           run_prefix,
                                                           save_prefix,
                                                           saddle=False)
                ene_abs = ene.read_energy(spc_dct_i,
                                          pf_filesystems,
                                          spc_mod_dct_i,
                                          run_prefix,
                                          conf=(locs, locs_path, cnf_fs),
                                          read_ene=True,
                                          read_zpe=True,
                                          saddle=False)
                hf0k, _, chn_basis_ene_dct, hbasis = basis.enthalpy_calculation(
                    spc_dct,
                    spc_name,
                    ene_abs,
                    chn_basis_ene_dct,
                    pes_mod_dct_i,
                    spc_mod_dct_i,
                    run_prefix,
                    save_prefix,
                    pforktp='pf',
                    zrxn=None)
                spc_basis, coeff_basis = hbasis[spc_name]
                coeff_array = []
                for spc_i in spc_basis:
                    if spc_i not in spc_array:
                        spc_array.append(spc_i)
                for spc_i in spc_array:
                    if spc_i in spc_basis:
                        coeff_array.append(coeff_basis[spc_basis.index(spc_i)])
                    else:
                        coeff_array.append(0)
                csv_data[label] = [locs_path, ene_abs, hf0k, *coeff_array]

    util.write_csv_data(tsk, csv_data, filelabel, spc_array)
Пример #6
0
def rpvtst_data(ts_dct,
                reac_dcts,
                spc_mod_dct_i,
                run_prefix,
                save_prefix,
                sadpt=False):
    """ Pull all of the neccessary information from the
        filesystem for a species
    """

    zrxn = ts_dct['zrxn']

    # Set up all the filesystem objects using models and levels
    if sadpt:
        # Set up filesystems and coordinates for saddle point
        # Scan along RxnCoord is under THY/TS/CONFS/cid/Z
        pf_filesystems = filesys.models.pf_filesys(ts_dct, spc_mod_dct_i,
                                                   run_prefix, save_prefix,
                                                   True)
        tspaths = pf_filesystems['harm']
        [_, cnf_save_path, min_locs, _, cnf_run_fs] = tspaths
        ts_run_path = cnf_run_fs[-1].path(min_locs)

        # Set TS reaction coordinate
        frm_name = 'IRC'
        scn_vals = filesys.models.get_rxn_scn_coords(cnf_save_path, frm_name)
        scn_vals.sort()
        scn_ene_info = spc_mod_dct_i['ene'][1][0][1]  # fix to be ene lvl
        scn_prefix = cnf_save_path
    else:
        # Set up filesystems and coordinates for reaction path
        # Scan along RxnCoord is under THY/TS/Z
        tspaths = filesys.models.set_rpath_filesys(ts_dct,
                                                   spc_mod_dct_i['rpath'][1])
        ts_run_path, _, _, thy_save_path = tspaths

        # Set TS reaction coordinate
        scn_vals = filesys.models.get_rxn_scn_coords(thy_save_path, frm_name)
        scn_vals.sort()
        scn_ene_info = spc_mod_dct_i['rpath'][1][0]
        scn_prefix = thy_save_path

    # Modify the scn thy info
    ioprinter.debug_message('scn thy info', scn_ene_info)
    ioprinter.info_message('scn vals', scn_vals)
    mod_scn_ene_info = filesys.inf.modify_orb_restrict(
        filesys.inf.get_spc_info(ts_dct), scn_ene_info)
    # scn thy info [[1.0, ['molpro2015', 'ccsd(t)', 'cc-pvdz', 'RR']]]

    # Need to read the sp vals along the scan. add to read
    ref_ene = 0.0
    enes, geoms, grads, hessians, _, _ = filesys.read.potential(
        [frm_name],
        [scn_vals],
        scn_prefix,
        mod_scn_ene_info,
        ref_ene,
        constraint_dct=None,  # No extra frozen treatments
        read_geom=True,
        read_grad=True,
        read_hess=True)
    script_str = autorun.SCRIPT_DCT['projrot']
    freqs = autorun.projrot.pot_frequencies(script_str, geoms, grads, hessians,
                                            ts_run_path)

    # Get the energies and zpes at R_ref
    if not sadpt:
        _, ene_hs_sr_ref, ene_hs_mr_ref = ene.rpath_ref_idx(
            ts_dct, scn_vals, frm_name, scn_prefix, spc_mod_dct_i['ene'],
            spc_mod_dct_i['rpath'][1])
    fr_idx = len(scn_vals) - 1
    zpe_ref = (sum(freqs[(fr_idx, )]) / 2.0) * phycon.WAVEN2KCAL

    # Get the reactants and infinite seperation energy
    reac_ene = 0.0
    ene_hs_sr_inf = 0.0
    for dct in reac_dcts:
        pf_filesystems = filesys.models.pf_filesys(dct, spc_mod_dct_i,
                                                   run_prefix, save_prefix,
                                                   False)
        new_spc_dct_i = {
            'ene': spc_mod_dct_i['ene'],
            'harm': spc_mod_dct_i['harm'],
            'tors': spc_mod_dct_i['tors']
        }
        reac_ene += ene.read_energy(dct,
                                    pf_filesystems,
                                    new_spc_dct_i,
                                    run_prefix,
                                    read_ene=True,
                                    read_zpe=True,
                                    saddle=sadpt)

        ioprinter.debug_message('rpath', spc_mod_dct_i['rpath'][1])
        new_spc_dct_i = {
            'ene': ['mlvl', [[1.0, spc_mod_dct_i['rpath'][1][2]]]],
            'harm': spc_mod_dct_i['harm'],
            'tors': spc_mod_dct_i['tors']
        }
        ene_hs_sr_inf += ene.read_energy(dct,
                                         pf_filesystems,
                                         new_spc_dct_i,
                                         run_prefix,
                                         read_ene=True,
                                         read_zpe=False)

    # Scale the scn values
    if sadpt:
        scn_vals = [val / 100.0 for val in scn_vals]
    # scn_vals = [val * phycon.BOHR2ANG for val in scn_vals]

    # Grab the values from the read
    inf_dct = {}
    inf_dct['rpath'] = []
    pot_info = zip(scn_vals, enes.values(), geoms.values(), freqs.values())
    for rval, pot, geo, frq in pot_info:

        # Scale the r-values

        # Get the relative energy (edit for radrad scans)
        zpe = (sum(frq) / 2.0) * phycon.WAVEN2KCAL
        if sadpt:
            zero_ene = (pot + zpe) * phycon.KCAL2EH
        else:
            ioprinter.debug_message('enes')
            ioprinter.debug_message('reac ene', reac_ene)
            ioprinter.debug_message('hs sr', ene_hs_sr_ref)
            ioprinter.debug_message('inf', ene_hs_sr_inf)
            ioprinter.debug_message('hs mr', ene_hs_mr_ref)
            ioprinter.debug_message('pot R', pot * phycon.KCAL2EH)
            ioprinter.debug_message('zpe', zpe)
            ioprinter.debug_message('zpe ref', zpe_ref)

            elec_ene = (ene_hs_sr_ref - ene_hs_sr_inf - ene_hs_mr_ref +
                        pot * phycon.KCAL2EH)
            zpe_pt = zpe - zpe_ref
            zero_ene = reac_ene + (elec_ene + zpe_pt * phycon.KCAL2EH)
            ioprinter.info_message('elec ene', elec_ene)
            ioprinter.info_message('zero ene', zero_ene)

        # ENE
        # ene = (reac_ene +
        #        ene_hs_sr(R_ref) - ene_hs_sr(inf) +
        #        ene_ls_mr(R_ref) - ene_hs_mr(R_ref) +
        #        ene_ls_mr(R) - ene_ls_mr(R_ref))
        # ene = (reac_ene +
        #        ene_hs_sr(R_ref) - ene_hs_sr(inf) -
        #        ene_hs_mr(R_ref) + ene_ls_mr(R))
        # inf_sep_ene = reac_ene + hs_sr_ene - hs_mr_ene
        # inf_sep_ene_p = (reac_ene +
        #                  hs_sr_ene(R_ref) - ene_hs_sr(inf) +
        #                  ls_mr_ene(R_ref) - hs_mr_ene(R_ref))
        # ene = inf_sep_ene_p + ene_ls_mr(R) - ene_ls_mr(R_ref)
        # ZPE
        # zpe = zpe(R) - zpe(inf)
        # or
        # zpe = zpe_ls_mr(R) - zpe_ls_mr(R_ref)

        # Set values constant across the scan
        elec_levels = ts_dct['elec_levels']

        # Create info dictionary and append to lst
        keys = ['rval', 'geom', 'freqs', 'elec_levels', 'ene_chnlvl']
        vals = [rval, geo, frq, elec_levels, zero_ene]
        inf_dct['rpath'].append(dict(zip(keys, vals)))

    # Calculate and store the imaginary mode
    if sadpt:
        _, imag, _ = vib.read_harmonic_freqs(pf_filesystems,
                                             run_prefix,
                                             zrxn=zrxn)
        ts_idx = scn_vals.index(0.00)
    else:
        imag = None
        ts_idx = 0
    inf_dct.update({'imag': imag})
    inf_dct.update({'ts_idx': ts_idx})

    return inf_dct
Пример #7
0
def mol_data(spc_name,
             spc_dct,
             pes_mod_dct_i,
             spc_mod_dct_i,
             chn_basis_ene_dct,
             run_prefix,
             save_prefix,
             calc_chn_ene=True,
             zrxn=None,
             spc_locs=None):
    """ Reads all required data from the SAVE filesystem for a molecule.
        Stores data into an info dictionary.

        All of the data that is read is determined by the models that
        are described in the pes and spc model dictionaries.

        :param spc_dct:
        :type spc_dct:
        :param pes_mod_dct_i: keyword dict of specific PES model
        :type pes_mod_dct_i: dict[]
        :param spc_mod_dct_i: keyword dict of specific species model
        :type spc_mod_dct_i: dict[]
        :param run_prefix: root-path to the run-filesystem
        :type run_prefix: str
        :param save_prefix: root-path to the save-filesystem
        :type save_prefix: str
        :rtype: dict[]
    """

    spc_dct_i = spc_dct[spc_name]
    ene_chnlvl = None
    ene_reflvl = None
    zpe = None
    hf0k = None
    hf0k_trs = None
    hf0k = None

    # Initialize all of the elements of the inf dct
    geom, sym_factor, freqs, imag, elec_levels = None, None, None, None, None
    allr_str, mdhr_dat = '', ''
    xmat, rovib_coups, rot_dists = None, None, None

    # Set up all the filesystem objects using models and levels
    pf_filesystems = filesys.models.pf_filesys(spc_dct_i,
                                               spc_mod_dct_i,
                                               run_prefix,
                                               save_prefix,
                                               zrxn is not None,
                                               name=spc_name,
                                               spc_locs=spc_locs)

    # Obtain rotation partition function information
    ioprinter.info_message('Obtaining info for rotation partition function...',
                           newline=1)
    geom = rot.read_geom(pf_filesystems)

    if typ.nonrigid_rotations(spc_mod_dct_i):
        rovib_coups, rot_dists = rot.read_rotational_values(pf_filesystems)

    # Obtain vibration partition function information
    ioprinter.info_message(
        'Preparing internal rotor info building partition functions...',
        newline=1)
    rotors = tors.build_rotors(spc_dct_i, pf_filesystems, spc_mod_dct_i)
    ioprinter.info_message(
        'Obtaining the vibrational frequencies and zpves...', newline=1)
    freqs, imag, zpe, _, tors_strs, _, _, _ = vib.full_vib_analysis(
        spc_dct_i, pf_filesystems, spc_mod_dct_i, run_prefix, zrxn=zrxn)
    allr_str = tors_strs[0]

    # ioprinter.info_message('zpe in mol_data test:', zpe)
    if typ.anharm_vib(spc_mod_dct_i):
        xmat = vib.read_anharmon_matrix(pf_filesystems)

    # Obtain symmetry factor
    ioprinter.info_message('Determining the symmetry factor...', newline=1)

    zma = None
    if zrxn:
        [_, cnf_save_path, _, _, _] = pf_filesystems['harm']
        # Build the rotors
        if cnf_save_path:
            zma_fs = autofile.fs.zmatrix(cnf_save_path)
            zma = zma_fs[-1].file.zmatrix.read([0])

    sym_factor = symm.symmetry_factor(pf_filesystems,
                                      spc_mod_dct_i,
                                      spc_dct_i,
                                      rotors,
                                      grxn=zrxn,
                                      zma=zma)

    # Obtain electronic energy levels
    elec_levels = spc_dct_i['elec_levels']

    # Obtain energy levels
    ioprinter.info_message('Obtaining the electronic energy + zpve...',
                           newline=1)
    if calc_chn_ene:
        chn_ene = ene.read_energy(spc_dct_i,
                                  pf_filesystems,
                                  spc_mod_dct_i,
                                  run_prefix,
                                  read_ene=True,
                                  read_zpe=False,
                                  saddle=zrxn is not None)
        ene_chnlvl = chn_ene + zpe

        zma = None
        # Determine info about the basis species used in thermochem calcs
        hf0k, hf0k_trs, chn_basis_ene_dct, _ = basis.enthalpy_calculation(
            spc_dct,
            spc_name,
            ene_chnlvl,
            chn_basis_ene_dct,
            pes_mod_dct_i,
            spc_mod_dct_i,
            run_prefix,
            save_prefix,
            zrxn=zrxn)

    ene_reflvl = None

    #  Build the energy transfer section strings
    if zrxn is None:
        ioprinter.info_message('Determining energy transfer parameters...',
                               newline=1)
        well_info = sinfo.from_dct(spc_dct_i)
        # ioprinter.debug_message('well_inf', well_info)
        # bath_info = ['InChI=1S/N2/c1-2', 0, 1]  # how to do...
        bath_info = ['InChI=1S/Ar', 0, 1]  # how to do...
        etrans_dct = etrans.build_etrans_dct(spc_dct_i)

        edown_str, collid_freq_str = etrans.make_energy_transfer_strs(
            well_info, bath_info, etrans_dct)
    else:
        edown_str, collid_freq_str = None, None

    # Create info dictionary
    keys = [
        'geom', 'sym_factor', 'freqs', 'imag', 'elec_levels', 'mess_hr_str',
        'mdhr_dat', 'xmat', 'rovib_coups', 'rot_dists', 'ene_chnlvl',
        'ene_reflvl', 'zpe_chnlvl', 'ene_tsref', 'edown_str', 'collid_freq_str'
    ]
    vals = [
        geom, sym_factor, freqs, imag, elec_levels, allr_str, mdhr_dat, xmat,
        rovib_coups, rot_dists, hf0k, ene_reflvl, zpe, hf0k_trs, edown_str,
        collid_freq_str
    ]
    inf_dct = dict(zip(keys, vals))

    return inf_dct, chn_basis_ene_dct
Пример #8
0
def atm_data(spc_dct, spc_name, pes_mod_dct_i, spc_mod_dct_i, run_prefix,
             save_prefix):
    """ Reads all required data from the SAVE filesystem for an atom.
        Stores data into an info dictionary.

        All of the data that is read is determined by the models that
        are described in the pes and spc model dictionaries.

        :param spc_dct:
        :type spc_dct:
        :param pes_mod_dct_i: keyword dict of specific PES model
        :type pes_mod_dct_i: dict[]
        :param spc_mod_dct_i: keyword dict of specific species model
        :type spc_mod_dct_i: dict[]
        :param run_prefix: root-path to the run-filesystem
        :type run_prefix: str
        :param save_prefix: root-path to the save-filesystem
        :type save_prefix: str
        :rtype: dict[]
    """

    spc_dct_i = spc_dct[spc_name]
    # Set up all the filesystem objects using models and levels
    pf_filesystems = filesys.models.pf_filesys(spc_dct_i, spc_mod_dct_i,
                                               run_prefix, save_prefix, False)

    ioprinter.info_message('Obtaining the geometry...', newline=1)
    geom = rot.read_geom(pf_filesystems)

    ioprinter.info_message('Obtaining the electronic energy...', newline=1)
    ene_chnlvl = ene.read_energy(spc_dct_i,
                                 pf_filesystems,
                                 spc_mod_dct_i,
                                 run_prefix,
                                 read_ene=True,
                                 read_zpe=False)

    hf0k, hf0k_trs, _, _ = basis.enthalpy_calculation(spc_dct,
                                                      spc_name,
                                                      ene_chnlvl, {},
                                                      pes_mod_dct_i,
                                                      spc_mod_dct_i,
                                                      run_prefix,
                                                      save_prefix,
                                                      pforktp='ktp',
                                                      zrxn=None)

    # Create info dictionary
    inf_dct = {
        'geom': geom,
        'sym_factor': 1.0,
        'freqs': tuple(),
        'mess_hr_str': '',
        'mass': util.atom_mass(spc_dct_i),
        'elec_levels': spc_dct_i['elec_levels'],
        'ene_chnlvl': hf0k,
        'ene_reflvl': None,
        'ene_tsref': hf0k_trs,
        'zpe_chnlvl': None
    }

    return inf_dct
Пример #9
0
def run(pes_rlst, spc_rlst,
        therm_tsk_lst,
        pes_mod_dct, spc_mod_dct,
        spc_dct,
        run_prefix, save_prefix):
    """ Executes all thermochemistry tasks.

        :param pes_rlst: species from PESs to run
            [(PES formula, PES idx, SUP-PES idx)
            (CHANNEL idx, (REACS, PRODS))
        :type pes_rlst: tuple(dict[str: dict])
        :param spc_rlst: lst of species to run
        :type spc_rlst: tuple(dict[str: dict])
        :param es_tsk_lst: list of the electronic structure tasks
            tuple(tuple(obj, tsk, keyword_dict))
        :type es_tsk_lst: tuple(tuple(str, str, dict))
        :param spc_dct: species information
            dict[spc_name: spc_information]
        :type spc_dct: dict[str:dict]
        :param glob_dct: global information for all species
            dict[spc_name: spc_information]
        :type glob_dct: dict[str: dict]
        :param thy_dct: all of the theory information
            dict[thy name: inf]
        :type thy_dct: dict[str:dict]
        :param run_prefix: root-path to the run-filesystem
        :type run_prefix: str
        :param save_prefix: root-path to the save-filesystem
        :type save_prefix: str
    """

    # Print Header
    ioprinter.info_message('Calculating Thermochem:')
    ioprinter.runlst(('SPC', 0, 0), spc_rlst)

    # ------------------------------------------------ #
    # PREPARE INFORMATION TO PASS TO THERMDRIVER TASKS #
    # ------------------------------------------------ #

    # Build a list of the species to calculate thermochem for loops below
    spc_mods = list(spc_mod_dct.keys())  # hack
    spc_mod_dct_i = spc_mod_dct[spc_mods[0]]
    split_rlst = split_unstable_full(
        pes_rlst, spc_rlst, spc_dct, spc_mod_dct_i, save_prefix)
    spc_queue = parser.rlst.spc_queue(
        tuple(split_rlst.values())[0], 'SPC')

    # Build the paths [(messpf, nasa)], models and levels for each spc
    thm_paths = thermo_paths(spc_dct, spc_queue, spc_mods, run_prefix)

    # ----------------------------------- #
    # RUN THE REQUESTED THERMDRIVER TASKS #
    # ----------------------------------- #

    # Write and Run MESSPF inputs to generate the partition functions
    write_messpf_tsk = parser.run.extract_task('write_mess', therm_tsk_lst)
    if write_messpf_tsk is not None:

        ioprinter.messpf('write_header')

        spc_mods, pes_mod = parser.models.extract_models(write_messpf_tsk)

        for idx, spc_name in enumerate(spc_queue):
            print('write test {}'.format(spc_name))
            for spc_mod in spc_mods:
                messpf_inp_str = thmroutines.qt.make_messpf_str(
                    pes_mod_dct[pes_mod]['therm_temps'],
                    spc_dct, spc_name,
                    pes_mod_dct[pes_mod], spc_mod_dct[spc_mod],
                    run_prefix, save_prefix)
                ioprinter.messpf('input_string')
                ioprinter.info_message(messpf_inp_str)
                autorun.write_input(
                    thm_paths[idx][spc_mod][0], messpf_inp_str,
                    input_name='pf.inp')

    # Run the MESSPF files that have been written
    run_messpf_tsk = parser.run.extract_task('run_mess', therm_tsk_lst)
    if run_messpf_tsk is not None:

        spc_mod, pes_mod = parser.models.extract_models(run_messpf_tsk)
        spc_mods = parser.models.split_model(spc_mod[0])

        ioprinter.messpf('run_header')
        for idx, spc_name in enumerate(spc_queue):

            _spc_mods, coeffs, operators = spc_mods

            # Run MESSPF for all requested models, combine the PFS at the end
            ioprinter.message('Run MESSPF: {}'.format(spc_name), newline=1)
            _pfs = []
            for spc_mod in _spc_mods:
                autorun.run_script(
                   autorun.SCRIPT_DCT['messpf'],
                   thm_paths[idx][spc_mod][0])
                _pfs.append(
                    reader.mess.messpf(thm_paths[idx][spc_mod][0]))
            final_pf = thermfit.pf.combine(_pfs, coeffs, operators)

            # need to clean thm path build
            tdx = len(spc_mods)
            spc_info = sinfo.from_dct(spc_dct[spc_name])
            spc_fml = automol.inchi.formula_string(spc_info[0])
            thm_prefix = [spc_fml, automol.inchi.inchi_key(spc_info[0])]
            thm_paths[idx]['final'] = (
                job_path(run_prefix, 'MESS', 'PF', thm_prefix, locs_idx=tdx),
                job_path(run_prefix, 'THERM', 'NASA', thm_prefix, locs_idx=tdx)
            )
            writer.mess.output(
                fstring(spc_dct[spc_name]['inchi']),
                final_pf, thm_paths[idx]['final'][0],
                filename='pf.dat')

    # Use MESS partition functions to compute thermo quantities
    run_fit_tsk = parser.run.extract_task('run_fits', therm_tsk_lst)
    if run_fit_tsk is not None:

        spc_mods, pes_mod = parser.models.extract_models(run_fit_tsk)
        pes_mod_dct_i = pes_mod_dct[pes_mod]

        ioprinter.nasa('header')
        chn_basis_ene_dct = {}
        for idx, spc_name in enumerate(spc_queue):

            # Take species model and add it to the chn_basis_ene dct
            spc_mod = spc_mods[0]
            spc_mod_dct_i = spc_mod_dct[spc_mod]
            if spc_mod not in chn_basis_ene_dct:
                chn_basis_ene_dct[spc_mod] = {}

            # Get the reference scheme and energies (ref in different place)
            ref_scheme = pes_mod_dct_i['therm_fit']['ref_scheme']
            ref_enes = pes_mod_dct_i['therm_fit']['ref_enes']

            # Determine info about the basis species used in thermochem calcs
            basis_dct, uniref_dct = thermfit.prepare_refs(
                ref_scheme, spc_dct, (spc_name,))

            # Get the basis info for the spc of interest
            spc_basis, coeff_basis = basis_dct[spc_name]

            # Get the energies for the spc and its basis
            ene_basis = []
            energy_missing = False
            for spc_basis_i in spc_basis:
                if spc_basis_i in chn_basis_ene_dct[spc_mod]:
                    ioprinter.message(
                        'Energy already found for basis species: '
                        + spc_basis_i)
                    ene_basis.append(chn_basis_ene_dct[spc_mod][spc_basis_i])
                else:
                    ioprinter.message(
                        'Energy will be determined for basis species: '
                        + spc_basis_i)
                    energy_missing = True
            if not energy_missing:
                pf_filesystems = filesys.models.pf_filesys(
                    spc_dct[spc_name], spc_mod_dct_i,
                    run_prefix, save_prefix, saddle=False)
                ene_spc = ene.read_energy(
                    spc_dct[spc_name], pf_filesystems, spc_mod_dct_i,
                    run_prefix, read_ene=True, read_zpe=True, saddle=False)
            else:
                ene_spc, ene_basis = thmroutines.basis.basis_energy(
                    spc_name, spc_basis, uniref_dct, spc_dct,
                    spc_mod_dct_i,
                    run_prefix, save_prefix)
                for spc_basis_i, ene_basis_i in zip(spc_basis, ene_basis):
                    chn_basis_ene_dct[spc_mod][spc_basis_i] = ene_basis_i

            # Calculate and store the 0 K Enthalpy
            hf0k = thermfit.heatform.calc_hform_0k(
                ene_spc, ene_basis, spc_basis, coeff_basis, ref_set=ref_enes)
            spc_dct[spc_name]['Hfs'] = [hf0k]

        # Write the NASA polynomials in CHEMKIN format
        ckin_nasa_str = ''
        ckin_path = output_path('CKIN')
        for idx, spc_name in enumerate(spc_queue):

            ioprinter.nasa('calculate', spc_name)

            # Write the header describing the models used in thermo calcs
            ckin_nasa_str += writer.ckin.model_header(spc_mods, spc_mod_dct)

            # Build and write the NASA polynomial in CHEMKIN-format string
            # Call dies if you haven't run "write mess" task
            ckin_nasa_str += thmroutines.nasapoly.build_polynomial(
                spc_name, spc_dct,
                thm_paths[idx]['final'][0], thm_paths[idx]['final'][1])
            ckin_nasa_str += '\n\n'
        print('CKIN NASA STR\n')
        print(ckin_nasa_str)

        nasa7_params_all = chemkin_io.parser.thermo.create_spc_nasa7_dct(
            ckin_nasa_str)
        ioprinter.info_message(
            'SPECIES\t\tH(0 K)[kcal/mol]\tH(298 K)[kcal/mol]\t' +
            'S(298 K)[cal/mol K]\n')
        for spc_name in nasa7_params_all:
            nasa7_params = nasa7_params_all[spc_name]
            ht0 = spc_dct[spc_name]['Hfs'][0]
            ht298 = mechanalyzer.calculator.thermo.enthalpy(
                nasa7_params, 298.15)
            st298 = mechanalyzer.calculator.thermo.entropy(
                nasa7_params, 298.15)
            ioprinter.info_message(
                '{}\t{:3.2f}\t{:3.2f}\t{:3.2f}'.format(
                    spc_name, ht0, ht298/1000., st298))

        # Write all of the NASA polynomial strings
        writer.ckin.write_nasa_file(ckin_nasa_str, ckin_path)
Пример #10
0
def basis_energy(spc_name,
                 spc_basis,
                 uni_refs_dct,
                 spc_dct,
                 spc_model_dct_i,
                 run_prefix,
                 save_prefix,
                 read_species=True):
    """ Return the electronic + zero point energies for a set of species.
    """

    # Initialize ich name dct to noe
    ich_name_dct = {}
    for ich in spc_basis:
        if isinstance(ich, str):
            ich_name_dct[ich] = None
        else:
            ich_name_dct[_ich_key_name(ich)] = None

    # Get names of the basis species from the respective spc dcts
    for ich in spc_basis:
        for name in spc_dct:
            if name != 'global' and 'ts' not in name:
                if ich == spc_dct[name]['inchi']:
                    ich_name_dct[ich] = name
            elif name != 'global':
                if 'reacs' in spc_dct[name]:
                    if _ich_in_rxn(ich, spc_dct[name]):
                        ich_name_dct[_ich_key_name(ich)] = name
        for name in uni_refs_dct:
            if 'TS' in name:
                ioprinter.info_message(uni_refs_dct[name]['reacs'])
                if _ich_in_rxn(ich, spc_dct[name]):
                    ich_name_dct[_ich_key_name(ich)] = name
            elif ich == uni_refs_dct[name]['inchi']:
                ich_name_dct[ich] = name

    # Check the ich_name_dct
    dct_incomplete = False
    for ich, name in ich_name_dct.items():
        if name is None:
            ioprinter.warning_message(
                '{} not given in species.csv file'.format(ich))
            dct_incomplete = True
    if dct_incomplete:
        ioprinter.error_message('Job ending since basis species not specified')
        sys.exit()

    # Get the species energy
    if read_species:
        ioprinter.info_message(
            'Calculating energy for species {}'.format(spc_name), newline=1)
        pf_filesystems = filesys.models.pf_filesys(spc_dct[spc_name],
                                                   spc_model_dct_i,
                                                   run_prefix,
                                                   save_prefix,
                                                   saddle='ts' in spc_name)
        h_spc = read_energy(spc_dct[spc_name],
                            pf_filesystems,
                            spc_model_dct_i,
                            run_prefix,
                            read_ene=True,
                            read_zpe=True,
                            saddle='ts' in spc_name)
        if h_spc is None:
            ioprinter.error_message('No energy found for {}'.format(spc_name))
            sys.exit()
    else:
        h_spc = None

    # Get the energies of the bases
    h_basis = []
    for ich, name in ich_name_dct.items():
        if name in spc_dct:
            spc_dct_i = spc_dct[name]
            prname = name
        elif name in uni_refs_dct:
            spc_dct_i = uni_refs_dct[name]
            prname = name
        if 'ts' in name or 'TS' in name:
            reacs, prods = ich.split('PRODS')
            reacs = reacs.replace('REACS', '')
            reacs = reacs.split('REAC')
            prods = prods.split('PROD')
            reac_lbl = 'r0'
            if len(reacs) > 1:
                reac_lbl += '+r1'
            prod_lbl = 'p0'
            if len(prods) > 1:
                prod_lbl += '+p1'
            ioprinter.info_message('Basis Reaction: {}={} 1 1 1 '.format(
                reac_lbl, prod_lbl))
            for i, reac in enumerate(reacs):
                ioprinter.info_message('r{},{},{},{}'.format(
                    str(i), reac, automol.inchi.smiles(reac), '1'))
            for i, prod in enumerate(prods):
                ioprinter.info_message('p{},{},{},{}'.format(
                    str(i), prod, automol.inchi.smiles(prod), '1'))
        ioprinter.debug_message('bases energies test:', ich, name)
        pf_filesystems = filesys.models.pf_filesys(
            spc_dct_i, spc_model_dct_i, run_prefix, save_prefix, 'ts' in name
            or 'TS' in name)
        ioprinter.info_message(
            'Calculating energy for basis {}...'.format(prname), newline=1)
        h_basis.append(
            read_energy(spc_dct_i,
                        pf_filesystems,
                        spc_model_dct_i,
                        run_prefix,
                        read_ene=True,
                        read_zpe=True,
                        saddle='ts' in name or 'TS' in name))

    # Check if all the energies found
    no_ene_cnt = 0
    for basis_ene, basis_name in zip(h_basis, ich_name_dct.values()):
        if basis_ene is None:
            ioprinter.warning_message(
                'No energy found for {}'.format(basis_name))
            no_ene_cnt += 1
    if no_ene_cnt > 1:
        ioprinter.error_message('Not all energies found for the basis species')
        sys.exit()

    return h_spc, h_basis