Exemple #1
0
def _set_sort_info_lst(sort_str, thy_dct, spc_info):
    """ Return the levels to sort conformers by if zpve or sp
        levels were assigned in input

        if we ask for zpe(lvl_wbs),sp(lvl_b2t),gibbs(700)
        out sort_info_lst will be [('gaussian', 'wb97xd', '6-31*', 'RU'),
        ('gaussian', 'b2plypd3', 'cc-pvtz', 'RU'), None, None, 700.]
    """
    sort_lvls = [None, None, None, None, None]
    sort_typ_lst = ['freqs', 'sp', 'enthalpy', 'entropy', 'gibbs']
    if sort_str is not None:
        for sort_param in sort_str.split(','):
            idx = None
            for typ_idx, typ_str in enumerate(sort_typ_lst):
                if typ_str in sort_param:
                    lvl_key = sort_str.split(typ_str + '(')[1].split(')')[0]
                    idx = typ_idx
            if idx is not None:
                if idx < 2:
                    method_dct = thy_dct.get(lvl_key)
                    if method_dct is None:
                        ioprinter.warning_message(
                            f'no {lvl_key} in theory.dat, '
                            f'not using {sort_typ_lst[idx]} in sorting')
                        continue
                    thy_info = tinfo.from_dct(method_dct)
                    mod_thy_info = tinfo.modify_orb_label(thy_info, spc_info)
                    sort_lvls[idx] = mod_thy_info
                else:
                    sort_lvls[idx] = float(lvl_key)
    return sort_lvls
Exemple #2
0
def saddle_point_checker(imags):
    """ run things for checking Hessian
    """

    big_imag, kick_imag = 0, 0

    ioprinter.checking('the imaginary frequencies of the saddle point...')
    if len(imags) < 1:
        ioprinter.warning_message('No imaginary modes for geometry')
        status = 'fail'
    else:
        if len(imags) > 1:
            ioprinter.warning_message('More than one imaginary mode for geometry')
        for idx, imag in enumerate(imags):
            if imag <= 50.0:
                ioprinter.warning_message('Mode {} {} cm-1 is low,'.format(str(idx+1), imag))
            elif 50.0 < imag <= 200.0:
                lowstr = 'Mode {} {} cm-1 is low,'.format(str(idx+1), imag)
                ioprinter.warning_message(lowstr + 'need a kickoff procedure to remove')
                kick_imag += 1
            else:
                ioprinter.debug_message('Mode {} {} cm-1 likely fine,'.format(str(idx+1), imag))
                big_imag += 1

        if big_imag > 1:
            ioprinter.warning_message('WARNING: More than one imaginary mode for geometry')
            if kick_imag >= 1:
                ioprinter.debug_message('Will kickoff to get saddle point')
                status = 'kickoff'
        elif big_imag == 1:
            status = 'success'

    return status
Exemple #3
0
def read_locs_harmonic_freqs(cnf_fs, cnf_locs, run_prefix, zrxn=None):
    """ Read the harmonic frequencies for a specific conformer
        Do the freqs obtain for two species for fake and pst?
    """

    if cnf_locs is not None:
        geo_exists = cnf_fs[-1].file.geometry.exists(cnf_locs)
        hess_exists = cnf_fs[-1].file.hessian.exists(cnf_locs)

        if not geo_exists:
            ioprinter.error_message(
                'No Reference geometry for harmonic frequencies at path',
                cnf_fs[-1].file.hessian.path(cnf_locs))
        if not hess_exists:
            ioprinter.error_message(
                'No Hessian available for harmonic frequencies at path',
                cnf_fs[-1].file.hessian.path(cnf_locs))
    else:
        geo_exists, hess_exists = False, False

    if geo_exists and hess_exists:
        # Obtain geom and freqs from filesys
        geo = cnf_fs[-1].file.geometry.read(cnf_locs)
        hess = cnf_fs[-1].file.hessian.read(cnf_locs)

        ioprinter.reading('Hessian', cnf_fs[-1].path(cnf_locs))

        # Build the run filesystem using locs
        fml_str = automol.geom.formula_string(geo)
        vib_path = job_path(run_prefix, 'PROJROT', 'FREQ', fml_str)

        # Obtain the frequencies
        ioprinter.info_message(
            'Calling ProjRot to diagonalize Hessian and get freqs...')
        script_str = autorun.SCRIPT_DCT['projrot']
        freqs, _, imag_freqs, _ = autorun.projrot.frequencies(
            script_str, vib_path, [geo], [[]], [hess])

        # Obtain the displacements
        norm_coord_str, _ = autorun.projrot.displacements(
            script_str, vib_path, [geo], [[]], [hess])

        # Calculate the zpve
        ioprinter.frequencies(freqs)
        zpe = (sum(freqs) / 2.0) * phycon.WAVEN2EH

        # Check imaginary frequencies and set freqs
        if zrxn is not None:
            if len(imag_freqs) > 1:
                ioprinter.warning_message('Saddle Point has more than',
                                          'one imaginary frequency')
            imag = imag_freqs[0]
        else:
            imag = None

        ret = (freqs, imag, zpe, norm_coord_str)
    else:
        ret = None

    return ret
Exemple #4
0
def _active_space_dictionary(job_path):
    """ Reads any active-space templates provided by the user in the directory
        where other input files. The function extracts the mechanism name
        from a top-line comment in the template file.

        Currently, only Molpro templates are supported.

        :param job_path: directory path where all input files exist
        :type job_path: str
        :rtype: tuple(str)
    """
    def _comment_name(aspace_str):
        """ read the species name from a comment line in template
            comment line in FIRST line of template of form
            ! {spc_name}
        """
        comm_line = aspace_str.splitlines()[0]
        comm_line.replace('!', '').strip()
        return comm_line

    aspace_dct, path_dct = {}, {}
    _inp_paths = _inp_file_paths(job_path)
    if _inp_paths:
        for file_path, file_name in _inp_paths:
            if file_path.endswith('.asp'):
                aspace_str = ioformat.pathtools.read_file(file_path, file_name)
                spc_name = _comment_name(aspace_str)
                if spc_name in aspace_dct:
                    warning_message(
                        f'Dupilicate active space geometry for {spc_name}')
                aspace_dct[spc_name] = aspace_str
                path_dct[spc_name] = file_name

    return aspace_dct, path_dct
Exemple #5
0
def _geometry_dictionary(job_path):
    """ Reads any .xyz files provided by the user in the directory
        where other input files. The function extracts the mechanism name
        of the species/transition-state from the comment line of the .xyz file
        and indexes each .xyz string with this name.

        :param job_path: directory path where all input files exist
        :type job_path: str
        :rtype: dict[str: str]
    """

    geo_dct, path_dct = {}, {}
    _inp_paths = _inp_file_paths(job_path)
    if _inp_paths:
        for file_path, file_name in _inp_paths:
            if file_path.endswith('.xyz'):
                xyz_str = ioformat.pathtools.read_file(file_path, file_name)
                spc_name = automol.geom.comment_from_xyz_string(xyz_str)
                geo = automol.geom.from_xyz_string(xyz_str)
                if spc_name in geo_dct:
                    warning_message(f'Dupilicate xyz geometry for {spc_name}')
                geo_dct[spc_name] = geo
                path_dct[spc_name] = file_name

    return geo_dct, path_dct
Exemple #6
0
def _reac_sep_ene(rct_info, sp_thy_info, rcts_cnf_fs, run_prefix, overwrite,
                  sp_script_str, **kwargs):
    """ Determine the sum of electronic energies of two reactants specified
        at the level of theory described in the theory info object. Will
        calculate the energy if it is not currently in the SAVE filesystem.
    """

    # get the single reference energy for each of the reactant configurations
    spc_enes = []
    for (run_fs, save_fs, mlocs, mpath), inf in zip(rcts_cnf_fs, rct_info):

        # Set the modified thy info
        mod_sp_thy_info = tinfo.modify_orb_label(sp_thy_info, inf)

        # Build filesys
        zma_fs = autofile.fs.zmatrix(mpath)

        # Read the geometry and set paths
        zma = zma_fs[-1].file.zmatrix.read([0])
        geo = save_fs[-1].file.geometry.read(mlocs)

        # Build the single point filesys objects
        sp_save_fs = autofile.fs.single_point(mpath)

        # Calculate the save single point energy
        sp.run_energy(zma, geo, inf, mod_sp_thy_info, run_fs, save_fs, mlocs,
                      run_prefix, sp_script_str, overwrite, **kwargs)
        exists = sp_save_fs[-1].file.energy.exists(mod_sp_thy_info[1:4])
        if not exists:
            ioprinter.warning_message('No ene found')
            ene = None
        else:
            ene = sp_save_fs[-1].file.energy.read(mod_sp_thy_info[1:4])

        # Append ene to list
        spc_enes.append(ene)

    # Analyze the energies in the list
    inf_ene = 0.0
    for ene, inf in zip(spc_enes, rct_info):
        if ene is not None:
            inf_ene += ene
        else:
            ioprinter.error_message(
                'Single reference energy job fails', f'for {inf}: ',
                'Energy needed to evaluate infinite separation energy')
            inf_ene = None

    if inf_ene is not None:
        ioprinter.info_message(f'Reactant Energy [au]: {inf_ene}')

    return inf_ene
Exemple #7
0
def set_model_filesys(spc_dct_i,
                      level,
                      run_prefix,
                      save_prefix,
                      saddle,
                      name=None,
                      cnf_range='min',
                      spc_locs=None,
                      nprocs=1):
    """ Gets filesystem objects for reading many calculations
    """

    # Set the spc_info
    if saddle:
        rxn_info = spc_dct_i['rxn_info']
        spc_info = rinfo.ts_info(rxn_info)
    else:
        spc_info = sinfo.from_dct(spc_dct_i)

    levelp = tinfo.modify_orb_label(level, spc_info)

    _root = root_locs(spc_dct_i, saddle=saddle, name=name)
    cnf_run_fs, cnf_save_fs = build_fs(run_prefix,
                                       save_prefix,
                                       'CONFORMER',
                                       thy_locs=levelp[1:],
                                       **_root)

    hbond_cutoffs = spc_dct_i['hbond_cutoffs']
    if cnf_range == 'specified':
        min_rngs_locs = spc_locs
        min_rngs_path = cnf_save_fs[-1].path(min_rngs_locs)
        cnf_run_fs[-1].create(min_rngs_locs)
    elif cnf_range == 'min':
        min_rngs_locs, min_rngs_path = min_energy_conformer_locators(
            cnf_save_fs, levelp, hbond_cutoffs=hbond_cutoffs)
        cnf_run_fs[-1].create(min_rngs_locs)
    else:
        min_rngs_locs_lst, min_rngs_path_lst = conformer_locators(
            cnf_save_fs,
            levelp,
            cnf_range=cnf_range,
            hbond_cutoffs=hbond_cutoffs,
            nprocs=nprocs)
        for min_locs in min_rngs_locs_lst:
            cnf_run_fs[-1].create(min_locs)
        min_rngs_locs = min_rngs_locs_lst[0]
        min_rngs_path = min_rngs_path_lst[0]
        ioprinter.warning_message('Only returning first location in this list')
    # Create run fs if that directory has been deleted to run the jobs

    return [cnf_save_fs, min_rngs_path, min_rngs_locs, '', cnf_run_fs]
Exemple #8
0
def _inchi_are_same(orig_ich, geo):
    """ Assess if a geometry has the same connectivity to
     saved geos evaluated in temrs of inchi
    """
    same = False
    ich = automol.geom.inchi(geo)
    assert automol.inchi.is_complete(orig_ich), (
        f'the inchi {orig_ich} orig_ich is not complete')
    if ich == orig_ich:
        same = True
    if not same:
        warning_message(f" - new inchi {ich} not the same as old {orig_ich}")

    return same
Exemple #9
0
def electronic_energy(spc_dct_i, pf_filesystems, spc_model_dct_i, conf=None):
    """ get high level energy at low level optimized geometry
    """

    ioprinter.info_message('- Calculating electronic energy')

    # spc_dct_i = spc_dct[spc_name]
    rxn_info = spc_dct_i.get('rxn_info', None)
    if rxn_info is not None:
        spc_info = rinfo.ts_info(rxn_info)
    else:
        spc_info = sinfo.from_dct(spc_dct_i)

    # Get the harmonic filesys information
    if conf:
        cnf_path = conf[1]
    else:
        [_, cnf_path, _, _, _] = pf_filesystems['harm']

    # Get the electronic energy levels
    ene_levels = tuple(val[1] for key, val in spc_model_dct_i['ene'].items()
                       if 'lvl' in key)
    print('ene levels', ene_levels)

    # Read the energies from the filesystem
    e_elec = None
    if os.path.exists(cnf_path):

        e_elec = 0.0
        # ioprinter.info_message('lvls', ene_levels)
        for (coeff, level) in ene_levels:
            # Build SP filesys
            mod_thy_info = tinfo.modify_orb_label(level, spc_info)
            sp_save_fs = autofile.fs.single_point(cnf_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):
                ioprinter.reading('Energy', sp_path)
                ene = sp_save_fs[-1].file.energy.read(mod_thy_info[1:4])
                e_elec += (coeff * ene)
            else:
                ioprinter.warning_message('No energy at path')
                e_elec = None
                break
    else:
        ioprinter.warning_message('No conformer to calculate the energy')

    return e_elec
Exemple #10
0
def saddle_point_checker(imags):
    """ run things for checking Hessian
    """

    big_imag, kick_imag = 0, 0

    ioprinter.checking('the imaginary frequencies of the saddle point...')
    if len(imags) < 1:
        ioprinter.warning_message('No imaginary modes for geometry')
        status = 'fail'
    else:
        if len(imags) > 1:
            ioprinter.warning_message(
                'More than one imaginary mode for geometry')
            status = 'fail'
        for idx, imag in enumerate(imags):
            if imag <= 50.0:
                ioprinter.warning_message(
                    f'Mode {str(idx+1)} {imag} cm-1 is low,')
            elif 50.0 < imag <= 200.0:
                lowstr = f'Mode {str(idx+1)} {imag} cm-1 is low,'
                ioprinter.debug_message(
                    lowstr + ' check mode and see if it should be corrected')
                big_imag += 1
                # Adding to the kick counter kills code for good TSs
                # Some addditions of big species have low mode of this
                # ioprinter.warning_message(
                #     lowstr + 'need a kickoff procedure to remove')
                # kick_imag += 1
            else:
                ioprinter.debug_message(
                    f'Mode {str(idx+1)} {imag} cm-1 likely fine')
                big_imag += 1

        if big_imag > 1:
            ioprinter.warning_message(
                'More than one imaginary mode for geometry')
            if kick_imag >= 1:
                ioprinter.debug_message('Will kickoff to get saddle point')
                status = 'kickoff'
            else:
                status = 'failure'
        elif big_imag == 1:
            status = 'success'
        elif big_imag == 0:
            status = 'failure'
            ioprinter.warning_message('Did not find any appropriate modes')

    return status
Exemple #11
0
def _inchi_are_same(orig_ich, geo):
    """ Assess if a geometry has the same connectivity to
     saved geos evaluated in temrs of inchi
    """
    same = False
    ich = automol.geom.inchi(geo)
    assert automol.inchi.is_complete(orig_ich), (
        'the inchi {} orig_ich is not complete'.format(orig_ich))
    if ich == orig_ich:
        same = True
    if not same:
        ioprinter.warning_message(
            " - new inchi {} not the same as old {}".format(ich, orig_ich))

    return same
Exemple #12
0
def _is_proper_isomer(cnf_save_fs, zma):
    """ Check if geom is the same isomer as those in the filesys
    """
    vma = automol.zmat.var_(zma)
    if cnf_save_fs[0].file.vmatrix.exists():
        exist_vma = cnf_save_fs[0].file.vmatrix.read()
        if vma != exist_vma:
            ioprinter.warning_message(
                " - Isomer is not the same as starting isomer. Skipping...")
            proper_isomer = False
        else:
            proper_isomer = True
    else:
        proper_isomer = False

    return proper_isomer
Exemple #13
0
def read_locs_harmonic_freqs(cnf_fs,
                             harm_path,
                             cnf_locs,
                             run_prefix,
                             zrxn=None):
    """ Read the harmonic frequencies for a specific conformer
    """

    # probably should read freqs
    # Do the freqs obtain for two species for fake and pst
    if cnf_locs is not None:

        # Obtain geom and freqs from filesys
        geo = cnf_fs[-1].file.geometry.read(cnf_locs)
        hess = cnf_fs[-1].file.hessian.read(cnf_locs)
        ioprinter.reading('Hessian', cnf_fs[-1].path(cnf_locs))

        # Build the run filesystem using locs
        fml_str = automol.geom.formula_string(geo)
        vib_path = job_path(run_prefix, 'PROJROT', 'FREQ', fml_str)

        # Obtain the frequencies
        ioprinter.info_message(
            'Calling ProjRot to diagonalize Hessian and get freqs...')
        script_str = autorun.SCRIPT_DCT['projrot']
        freqs, _, imag_freqs, _ = autorun.projrot.frequencies(
            script_str, vib_path, [geo], [[]], [hess])

        # Calculate the zpve
        ioprinter.frequencies(freqs)
        zpe = (sum(freqs) / 2.0) * phycon.WAVEN2EH

        # Check imaginary frequencies and set freqs
        if zrxn is not None:
            if len(imag_freqs) > 1:
                ioprinter.warning_message('Saddle Point has more than',
                                          'one imaginary frequency')
            imag = imag_freqs[0]
        else:
            imag = None

    else:
        ioprinter.error_message(
            'Reference geometry is missing for harmonic frequencies')

    return freqs, imag, zpe
Exemple #14
0
def _check_imaginary(spc_info, geo, mod_thy_info, run_fs, script_str,
                     overwrite=False, **kwargs):
    """ check if species has an imaginary frequency
    """

    # Initialize info
    has_imag = False
    norm_coords = []
    hess = ((), ())

    # Run Hessian calculation
    success, ret = es_runner.execute_job(
        job=elstruct.Job.HESSIAN,
        spc_info=spc_info,
        thy_info=mod_thy_info,
        geo=geo,
        run_fs=run_fs,
        script_str=script_str,
        overwrite=overwrite,
        **kwargs,
        )

    # Check for imaginary modes
    if success:
        inf_obj, _, out_str = ret
        prog = inf_obj.prog
        hess = elstruct.reader.hessian(prog, out_str)

        # Calculate vibrational frequencies
        if hess:
            run_path = run_fs[-1].path([elstruct.Job.HESSIAN])
            # run_path = run_fs[-1].path(['VIB'])
            script_str = autorun.SCRIPT_DCT['projrot']
            _, _, imag_freq, _ = autorun.projrot.frequencies(
               script_str, run_path, [geo], [[]], [hess])

            # Mode for now set the imaginary frequency check to -100:
            # Should decrease once freq projector functions properly
            if imag_freq:
                ioprinter.warning_message('Imaginary mode found:')
                norm_coords = elstruct.reader.normal_coordinates(prog, out_str)
                has_imag = True

    return has_imag, norm_coords
Exemple #15
0
def _check_freqs(imags):
    """ Check the magnitude of the imaginary modes.
    """

    big_imag, kick_imag = 0, 0

    ioprinter.checking('the imaginary frequencies of the saddle point...')
    if len(imags) < 1:
        ioprinter.warning_message('No imaginary modes for geometry')
        status = 'fail'
    else:
        if len(imags) > 1:
            ioprinter.warning_message(
                'More than one imaginary mode for geometry')
            status = 'fail'
        for idx, imag in enumerate(imags):
            if imag <= 50.0:
                ioprinter.warning_message(f'Mode {idx+1} {imag} cm-1 is low,')
            elif 50.0 < imag <= 200.0:
                lowstr = f'Mode {idx+1} {imag} cm-1 is low,'
                ioprinter.debug_message(
                    lowstr + ' check mode and see if it should be corrected')
                big_imag += 1
                # Adding to the kick counter kills code for good TSs
                # Some addditions of big species have low mode of this
                # ioprinter.warning_message(
                #     lowstr + 'need a kickoff procedure to remove')
                # kick_imag += 1
            else:
                ioprinter.debug_message(
                    f'Mode {idx+1} {imag} cm-1 is likely fine,')
                big_imag += 1

        if big_imag > 1:
            ioprinter.warning_message(
                'More than one imaginary mode for geometry')
            if kick_imag >= 1:
                ioprinter.debug_message('Will kickoff to get saddle point')
                status = 'kick'
            else:
                status = False
        elif big_imag == 1:
            status = True
        elif big_imag == 0:
            status = False

    return status
Exemple #16
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
Exemple #17
0
def _make_fake_mess_strs(chnl, side, fake_inf_dcts, chnl_enes, label_dct,
                         side_label):
    """ write the MESS strings for the fake wells and TSs
    """

    # Set vars based on the reacs/prods
    reacs, prods = chnl
    if side == 'reacs':
        well_key = 'fake_vdwr'
        ts_key = 'fake_vdwr_ts'
        prepend_key = 'FRB'
        side_idx = 0
    elif side == 'prods':
        well_key = 'fake_vdwp'
        ts_key = 'fake_vdwp_ts'
        side_idx = 1
        if reacs in (prods, prods[::-1]):
            prepend_key = 'FRB'
        else:
            prepend_key = 'FPB'

    # Initialize well and ts strs and data dcts
    fake_dat_dct = {}
    well_str, ts_str = '', ''

    # Build a fake TS dct
    ts_inf_dct = {'n_pst': 6.0, 'cn_pst': 10.0}

    # MESS string for the fake reactant side well
    well_dct_key = make_rxn_str(chnl[side_idx], prepend='F')
    well_dct_key_rev = make_rxn_str(chnl[side_idx][::-1], prepend='F')
    if well_dct_key in label_dct:
        fake_well_label = label_dct[well_dct_key]
    elif well_dct_key_rev in label_dct:
        fake_well_label = label_dct[well_dct_key_rev]
    else:
        ioprinter.warning_message(f'No label {well_dct_key} in label dict')
    # well_str += mess_io.writer.species_separation_str()
    _side_str = '+'.join(chnl[side_idx])
    aux_str = f'Fake Well for {_side_str}'
    fake_well, well_dat = blocks.fake_species_block(*fake_inf_dcts)
    well_str += mess_io.writer.well(fake_well_label,
                                    fake_well,
                                    aux_id_label=aux_str,
                                    zero_ene=chnl_enes[well_key])

    # MESS PST TS string for fake reactant side well -> reacs
    pst_dct_key = make_rxn_str(chnl[side_idx], prepend=prepend_key)
    pst_dct_key_rev = make_rxn_str(chnl[side_idx][::-1], prepend=prepend_key)
    if pst_dct_key in label_dct:
        pst_label = label_dct[pst_dct_key]
    elif pst_dct_key_rev in label_dct:
        pst_label = label_dct[pst_dct_key_rev]
    else:
        ioprinter.warning_message(f'No label {pst_dct_key} in label dict')
    pst_ts_str, pst_ts_dat = blocks.pst_block(ts_inf_dct, *fake_inf_dcts)
    ts_str += '\n' + mess_io.writer.ts_sadpt(pst_label,
                                             side_label,
                                             fake_well_label,
                                             pst_ts_str,
                                             aux_id_label=None,
                                             zero_ene=chnl_enes[ts_key],
                                             tunnel='')

    # Build the data dct
    if well_dat:
        fake_dat_dct.update(well_dat)
    if pst_ts_dat:
        fake_dat_dct.update(pst_ts_dat)

    return well_str, ts_str, fake_well_label, fake_dat_dct
Exemple #18
0
def _make_channel_mess_strs(tsname,
                            reacs,
                            prods,
                            pesgrp_num,
                            spc_dct,
                            label_dct,
                            written_labels,
                            pes_param_dct,
                            chnl_infs,
                            chnl_enes,
                            spc_model_dct_i,
                            unstable_chnl=False):
    """ For each reaction channel on the PES: take all of the pre-read and
        pre-processed information from the save filesys for the
        reactants, products, and transition state and write the appropriately
        formatted MESS input strings that will eventually be combined into the
        entire MESS input file.

        Also returns dictionary for all additional auxiliary data files,
        formatted as {file name: file string}, required by MESS.

        List of labels corresponding to MESS strings that have already been
        written and added to master string, meaning that species string does
        not need to be written again. Required since species appear on multiple
        channels.

        :param tsname: mechanism name of the transition state
        :param reacs: mechanisms name for the reactants of the reaction channel
        :type reacs: tuple(str)
        :param prods: mechanisms name for the products of the reaction channel
        :type prods: tuple(str)
        :param label_dct: mapping between mechanism name and MESS input label
        :type label_dct: dict[str: str]
        :param written_labels:
        :type written_labels:
        :param chnl_infs: collated molecular info obtained from save filesys
        :type chnl_infs: dict[str:__]
        :param chnl_enes: energies for channel, relative to PES reference
        :type chnl_enes: dict[str:float]
        :rtype: (str, str, str), str, dict[str:str]

    """

    # Initialize empty strings
    bi_str, well_str, ts_str = '', '', ''
    full_dat_dct = {}

    # Write the MESS string for the channel reactant(s) and product(s)
    for side in ('reacs', 'prods'):

        # Get information from relevant dictionaries
        rgt_names = reacs if side == 'reacs' else prods
        rgt_infs = chnl_infs[side]
        rgt_ene = chnl_enes[side]

        # Build the species string for reactant(s)/product(s)
        # Skip molec string building for termolecular species (may need agn)
        spc_strs = []
        if len(rgt_names) < 3:
            for inf in rgt_infs:
                spc_str, dat_dct = _make_spc_mess_str(inf)
                spc_strs.append(spc_str)
                full_dat_dct.update(dat_dct)

        # Set the labels to put into the file
        spc_labels = ()
        for name in rgt_names:
            if name in label_dct:
                spc_labels += (label_dct[name], )
            else:
                spc_labels += (name, )

        aux_labels = tuple(
            automol.inchi.smiles(spc_dct[name]['inchi']) for name in rgt_names)

        # spc_label = [automol.inchi.smiles(spc_dct[name]['inchi'])
        #              for name in rgt_names]
        _rxn_str = make_rxn_str(rgt_names)
        _rxn_str_rev = make_rxn_str(rgt_names[::-1])
        if _rxn_str in label_dct:
            chn_label = label_dct[_rxn_str]
        elif _rxn_str_rev in label_dct:
            chn_label = label_dct[_rxn_str_rev]
        else:
            ioprinter.warning_message(f'no {_rxn_str} in label dct')

        # Write the strings
        if chn_label not in written_labels:
            written_labels.append(chn_label)
            if len(rgt_names) == 3:
                aux_str = f'{spc_labels[0]}+{spc_labels[1]}+{spc_labels[2]}'
                bi_str += mess_io.writer.dummy(chn_label,
                                               aux_id_label=aux_str,
                                               zero_ene=rgt_ene)
            elif len(rgt_names) == 2:
                # Determine if product densities should be calc'd
                if side == 'prods':
                    calc_dens = set_prod_density_param(rgt_names, pesgrp_num,
                                                       pes_param_dct)
                else:
                    calc_dens = (False, False)

                aux_str = f'{spc_labels[0]} + {spc_labels[1]}'
                bi_str += mess_io.writer.bimolecular(
                    chn_label,
                    spc_labels[0],
                    spc_strs[0],
                    spc_labels[1],
                    spc_strs[1],
                    rgt_ene,
                    auxbimol_id_label=aux_str,
                    aux1_id_label=aux_labels[0],
                    aux2_id_label=aux_labels[1],
                    calc_spc1_density=calc_dens[0],
                    calc_spc2_density=calc_dens[1]) + '\n'
            else:
                edown_str = rgt_infs[0].get('edown_str', None)
                collid_freq_str = rgt_infs[0].get('collid_freq_str', None)

                well_str += mess_io.writer.well(
                    chn_label,
                    spc_strs[0],
                    aux_id_label=aux_labels[0],
                    zero_ene=rgt_ene,
                    edown_str=edown_str,
                    collid_freq_str=collid_freq_str) + '\n'

        # Initialize the reactant and product MESS label
        if side == 'reacs':
            reac_label = chn_label
            inner_reac_label = chn_label
        else:
            prod_label = chn_label
            inner_prod_label = chn_label

    # For abstractions: Write MESS strings for fake reac and prod wells and TS
    if chnl_infs.get('fake_vdwr', None) is not None:

        # Write all the MESS Strings for Fake Wells and TSs
        fwell_str, fts_str, fake_lbl, fake_dct = _make_fake_mess_strs(
            (reacs, prods), 'reacs', chnl_infs['fake_vdwr'], chnl_enes,
            label_dct, reac_label)

        # Append the fake strings to overall strings
        well_str += fwell_str + '\n'
        ts_str += fts_str

        # Re-set the reactant label for the inner transition state
        inner_reac_label = fake_lbl

        # Update the data string dct if necessary
        full_dat_dct.update(fake_dct)

    if chnl_infs.get('fake_vdwp', None) is not None:

        # Write all the MESS Strings for Fake Wells and TSs
        fwell_str, fts_str, fake_lbl, fake_dct = _make_fake_mess_strs(
            (reacs, prods), 'prods', chnl_infs['fake_vdwp'], chnl_enes,
            label_dct, prod_label)

        # Append the fake strings to overall strings
        well_str += fwell_str + '\n'
        ts_str += fts_str

        # Reset the product labels for the inner transition state
        inner_prod_label = fake_lbl

        # Update the data string dct if necessary
        full_dat_dct.update(fake_dct)

    # Write MESS string for the inner transition state; append full
    # Label has to correspond only to base name (ignores configuration)
    ts_label = label_dct[tsname]
    rclass = spc_dct[tsname + '_0']['class']
    sts_str, ts_dat_dct = _make_ts_mess_str(chnl_infs,
                                            chnl_enes,
                                            spc_model_dct_i,
                                            rclass,
                                            ts_label,
                                            inner_reac_label,
                                            inner_prod_label,
                                            unstable_chnl=unstable_chnl)
    ts_str += sts_str
    full_dat_dct.update(ts_dat_dct)

    return ((well_str, bi_str, ts_str), full_dat_dct, written_labels)
Exemple #19
0
def run_tau(zma, spc_info, thy_info, nsamp, tors_range_dct,
            tau_run_fs, tau_save_fs, script_str, overwrite,
            saddle, **kwargs):
    """ run sampling algorithm to find tau dependent geometries
    """
    if not tors_range_dct:
        ioprinter.info_message(
            "No torsional coordinates. Setting nsamp to 1.")
        nsamp = 1

    tau_save_fs[0].create()

    vma = automol.zmat.var_(zma)
    if tau_save_fs[0].file.vmatrix.exists():
        existing_vma = tau_save_fs[0].file.vmatrix.read()
        assert vma == existing_vma
    tau_save_fs[0].file.vmatrix.write(vma)
    idx = 0
    nsamp0 = nsamp
    inf_obj = autofile.schema.info_objects.tau_trunk(0, tors_range_dct)
    while True:
        if tau_save_fs[0].file.info.exists():
            inf_obj_s = tau_save_fs[0].file.info.read()
            nsampd = inf_obj_s.nsamp
        elif tau_run_fs[0].file.info.exists():
            inf_obj_r = tau_run_fs[0].file.info.read()
            nsampd = inf_obj_r.nsamp
        else:
            nsampd = 0

        nsamp = nsamp0 - nsampd
        if nsamp <= 0:
            ioprinter.info_message(
                'Reached requested number of samples. ',
                'Tau sampling complete.')
            break

        ioprinter.info_message("New nsamp is {:d}.".format(nsamp), indent=1)

        samp_zma, = automol.zmat.samples(zma, 1, tors_range_dct)
        tid = autofile.schema.generate_new_tau_id()
        locs = [tid]

        tau_run_fs[-1].create(locs)
        tau_run_prefix = tau_run_fs[-1].path(locs)
        run_fs = autofile.fs.run(tau_run_prefix)

        idx += 1
        ioprinter.info_message("Run {}/{}".format(idx, nsamp0))

        ioprinter.debug_message(
            'Checking if ZMA has high repulsion...', newline=1)
        geo = automol.zmat.geometry(zma)
        samp_geo = automol.zmat.geometry(samp_zma)
        if automol.pot.low_repulsion_struct(geo, samp_geo):
            ioprinter.debug_message('ZMA fine.')
            es_runner.run_job(
                job=elstruct.Job.OPTIMIZATION,
                script_str=script_str,
                run_fs=run_fs,
                geo=samp_zma,
                spc_info=spc_info,
                thy_info=thy_info,
                saddle=saddle,
                overwrite=overwrite,
                frozen_coordinates=tors_range_dct.keys(),
                **kwargs
            )
        else:
            ioprinter.warning_message('repulsive ZMA:')
            inp_str = elstruct.writer.optimization(
                geo=samp_zma,
                charge=spc_info[1],
                mult=spc_info[2],
                method=thy_info[1],
                basis=thy_info[2],
                prog=thy_info[0],
                orb_type=thy_info[3],
                mol_options=['nosym'],
                frozen_coordinates=tors_range_dct.keys(),
            )
            tau_run_fs[-1].file.geometry_input.write(inp_str, locs)
            ioprinter.warning_message(
                'geometry for bad ZMA at', tau_run_fs[-1].path(locs))

        # nsampd += 1
        # inf_obj.nsamp = nsampd
        # tau_save_fs[0].file.info.write(inf_obj)
        # tau_run_fs[0].file.info.write(inf_obj)

        if tau_save_fs[0].file.info.exists():
            inf_obj_s = tau_save_fs[0].file.info.read()
            nsampd = inf_obj_s.nsamp
        elif tau_run_fs[0].file.info.exists():
            inf_obj_r = tau_run_fs[0].file.info.read()
            nsampd = inf_obj_r.nsamp
        nsampd += 1
        inf_obj.nsamp = nsampd
        tau_save_fs[0].file.info.write(inf_obj)
        tau_run_fs[0].file.info.write(inf_obj)
Exemple #20
0
def _make_channel_mess_strs(tsname, reacs, prods,
                            spc_dct, label_dct, written_labels,
                            chnl_infs, chnl_enes, spc_model_dct_i):
    """ make the partition function strings for each of the channels
    includes strings for each of the unimolecular wells, bimolecular fragments,
    and transition states connecting them.
    It also includes a special treatment for abstraction to include phase space
    blocks and coupling bimolecular fragments to fake van der Waals wells
    """

    # Initialize empty strings
    bi_str, well_str, ts_str = '', '', ''
    full_dat_dct = {}

    # Write the MESS string for the channel reactant(s) and product(s)
    for side in ('reacs', 'prods'):

        # Get information from relevant dictionaries
        rgt_names = reacs if side == 'reacs' else prods
        rgt_infs = chnl_infs[side]
        rgt_ene = chnl_enes[side]

        # Build the species string for reactant(s)/product(s)
        # Skip molec string building for termolecular species (may need agn)
        spc_strs = []
        if len(rgt_names) < 3:
            for inf in rgt_infs:
                spc_str, dat_dct = _make_spc_mess_str(inf)
                spc_strs.append(spc_str)
                full_dat_dct.update(dat_dct)

        # Set the labels to put into the file
        spc_label = [automol.inchi.smiles(spc_dct[name]['inchi'])
                     for name in rgt_names]
        _rxn_str = make_rxn_str(rgt_names)
        _rxn_str_rev = make_rxn_str(rgt_names[::-1])
        if _rxn_str in label_dct:
            chn_label = label_dct[_rxn_str]
        elif _rxn_str_rev in label_dct:
            chn_label = label_dct[_rxn_str_rev]
        else:
            ioprinter.warning_message('no {} in label dct'.format(_rxn_str))

        # Write the strings
        if chn_label not in written_labels:
            written_labels.append(chn_label)
            if len(rgt_names) == 3:
                bi_str += '\n! {} + {} + {}\n'.format(
                    rgt_names[0], rgt_names[1], rgt_names[2])
                bi_str += mess_io.writer.dummy(chn_label, zero_ene=rgt_ene)
                # bi_str += '\n! DUMMY FOR UNSTABLE SPECIES\n'
                # bi_str += mess_io.writer.dummy(chn_label, zero_ene=None)
            elif len(rgt_names) == 2:
                # bi_str += mess_io.writer.species_separation_str()
                bi_str += '\n! {} + {}\n'.format(rgt_names[0], rgt_names[1])
                bi_str += mess_io.writer.bimolecular(
                    chn_label, spc_label[0], spc_strs[0],
                    spc_label[1], spc_strs[1], rgt_ene)
            else:
                edown_str = rgt_infs[0].get('edown_str', None)
                collid_freq_str = rgt_infs[0].get('collid_freq_str', None)

                # well_str += mess_io.writer.species_separation_str()
                well_str += '\n! {}\n'.format(rgt_names[0])
                well_str += mess_io.writer.well(
                    chn_label, spc_strs[0],
                    zero_ene=rgt_ene,
                    edown_str=edown_str,
                    collid_freq_str=collid_freq_str)

        # Initialize the reactant and product MESS label
        if side == 'reacs':
            reac_label = chn_label
            inner_reac_label = chn_label
        else:
            prod_label = chn_label
            inner_prod_label = chn_label

    # For abstractions: Write MESS strings for fake reac and prod wells and TS
    if chnl_infs.get('fake_vdwr', None) is not None:

        # Write all the MESS Strings for Fake Wells and TSs
        fwell_str, fts_str, fake_lbl, fake_dct = _make_fake_mess_strs(
            (reacs, prods), 'reacs', chnl_infs['fake_vdwr'],
            chnl_enes, label_dct, reac_label)

        # Append the fake strings to overall strings
        well_str += fwell_str
        ts_str += fts_str

        # Re-set the reactant label for the inner transition state
        inner_reac_label = fake_lbl

        # Update the data string dct if necessary
        full_dat_dct.update(fake_dct)

    if chnl_infs.get('fake_vdwp', None) is not None:

        # Write all the MESS Strings for Fake Wells and TSs
        fwell_str, fts_str, fake_lbl, fake_dct = _make_fake_mess_strs(
            (reacs, prods), 'prods', chnl_infs['fake_vdwp'],
            chnl_enes, label_dct, prod_label)

        # Append the fake strings to overall strings
        well_str += fwell_str
        ts_str += fts_str

        # Reset the product labels for the inner transition state
        inner_prod_label = fake_lbl

        # Update the data string dct if necessary
        full_dat_dct.update(fake_dct)

    # Write MESS string for the inner transition state; append full
    ts_label = label_dct[tsname]
    rclass = spc_dct[tsname+'_0']['class']
    sts_str, ts_dat_dct = _make_ts_mess_str(
        chnl_infs, chnl_enes, spc_model_dct_i, rclass,
        ts_label, inner_reac_label, inner_prod_label)
    ts_str += sts_str
    full_dat_dct.update(ts_dat_dct)

    return [well_str, bi_str, ts_str], full_dat_dct, written_labels
Exemple #21
0
def _write_varecof_input(ref_zma, ts_info, ts_formula, high_mul, rct_ichs,
                         rct_info, rct_zmas, active_space,
                         mod_var_sp1_thy_info, npot, inf_sep_ene, min_idx,
                         max_idx, vrc_dct, vrc_path, script_str):
    """ prepare all the input files for a vrc-tst calculation
    """

    r1dists_lr = vrc_dct['r1dists_lr']
    r1dists_sr = vrc_dct['r1dists_sr']
    r2dists_sr = vrc_dct['r2dists_sr']
    d1dists = vrc_dct['d1dists']
    d2dists = vrc_dct['d2dists']
    conditions = vrc_dct['conditions']
    nsamp_max = vrc_dct['nsamp_max']
    nsamp_min = vrc_dct['nsamp_min']
    flux_err = vrc_dct['flux_err']
    pes_size = vrc_dct['pes_size']
    base_name = vrc_dct['base_name']
    # exe_path = vrc_dct['exe_path']

    # Build geometries needed for the varecof run
    total_geom, frag_geoms, frag_geoms_wdummy = fragment_geometries(
        ref_zma, rct_zmas, min_idx, max_idx)

    # Set information for the pivot points needed in divsur.inp
    frames, npivots = build_pivot_frames(min_idx, max_idx, total_geom,
                                         frag_geoms, frag_geoms_wdummy)
    pivot_angles = calc_pivot_angles(frag_geoms, frag_geoms_wdummy, frames)
    pivot_xyzs = calc_pivot_xyzs(min_idx, max_idx, total_geom, frag_geoms)

    # Write the long- and short-range divsur input files
    lrdivsur_inp_str = varecof_io.writer.input_file.divsur(
        r1dists_lr, 1, 1, [0.0, 0.0, 0.0], [0.0, 0.0, 0.0])

    # Write the short-range divsur files
    t1angs = [pivot_angles[0]] if pivot_angles[0] is not None else []
    t2angs = [pivot_angles[1]] if pivot_angles[1] is not None else []
    if automol.geom.is_atom(frag_geoms[0]):
        d1dists = []
        t1angs = []
    if automol.geom.is_atom(frag_geoms[1]):
        d2dists = []
        t2angs = []
    if automol.geom.is_linear(frag_geoms[0]):
        d1dists = [0.]
        t1angs = []
    if automol.geom.is_linear(frag_geoms[1]):
        d2dists = [0.]
        t2angs = []
    if all(npiv > 1 for npiv in npivots):
        r2dists = r2dists_sr
    else:
        r2dists = []
        ioprinter.warning_message('no r2dist')

    srdivsur_inp_str = varecof_io.writer.input_file.divsur(r1dists_sr,
                                                           npivots[0],
                                                           npivots[1],
                                                           pivot_xyzs[0],
                                                           pivot_xyzs[1],
                                                           frame1=frames[0],
                                                           frame2=frames[1],
                                                           d1dists=d1dists,
                                                           d2dists=d2dists,
                                                           t1angs=t1angs,
                                                           t2angs=t2angs,
                                                           r2dists=r2dists,
                                                           **conditions)

    # Build the structure input file string
    struct_inp_str = varecof_io.writer.input_file.structure(
        frag_geoms_wdummy[0], frag_geoms_wdummy[1])

    # Write the structure and divsur files to get the divsur out file
    inp = ((struct_inp_str, 'structure.inp'), (srdivsur_inp_str, 'divsur.inp'))
    _write_varecof_inp(inp, vrc_path)

    # Obtain the divsur.out file with divsur-frame fragment geoms
    divsur_out_str = build_divsur_out_file(vrc_path, os.getcwd())

    # Write the tst.inp file
    faces, faces_symm = assess_face_symmetries(divsur_out_str)
    tst_inp_str = varecof_io.writer.input_file.tst(nsamp_max,
                                                   nsamp_min,
                                                   flux_err,
                                                   pes_size,
                                                   faces=faces,
                                                   faces_symm=faces_symm)

    # Write the molpro executable and potential energy surface input string
    els_inp_str = varecof_io.writer.input_file.elec_struct(
        vrc_path,
        base_name,
        npot,
        dummy_name='dummy_corr_',
        lib_name='libcorrpot.so',
        exe_name='molpro.sh',
        geom_ptt='GEOMETRY_HERE',
        ene_ptt='molpro_energy')

    # Write the electronic structure template file
    tml_inp_str = _build_molpro_template_str(ref_zma, ts_info, ts_formula,
                                             high_mul, rct_ichs, rct_info,
                                             active_space,
                                             mod_var_sp1_thy_info, inf_sep_ene)

    # Write the mc_flux.inp input string
    mc_flux_inp_str = varecof_io.writer.input_file.mc_flux()

    # Write the convert.inp input string
    conv_inp_str = varecof_io.writer.input_file.convert()

    # Write machines file to set compute nodes
    machine_file_str = build_machinefile_str()

    # Collate the input strings and write the remaining files
    input_strs = (lrdivsur_inp_str, tst_inp_str, els_inp_str, tml_inp_str,
                  mc_flux_inp_str, conv_inp_str, machine_file_str, script_str)
    input_names = ('lr_divsur.inp', 'tst.inp', 'molpro.inp', 'mol.tml',
                   'mc_flux.inp', 'convert.inp', 'machines', 'molpro.sh')
    inp = tuple(zip(input_strs, input_names))
    _write_varecof_inp(inp, vrc_path)
Exemple #22
0
def conformer_sampling(zma,
                       spc_info,
                       thy_info,
                       cnf_run_fs,
                       cnf_save_fs,
                       rid,
                       script_str,
                       overwrite,
                       nsamp_par=(False, 3, 3, 1, 50, 50),
                       tors_names=(),
                       zrxn=None,
                       two_stage=False,
                       retryfail=False,
                       resave=False,
                       **kwargs):
    """ run sampling algorithm to find conformers
    """

    # Check if any saving needs to be done before hand
    if resave:
        _presamp_save(spc_info,
                      cnf_run_fs,
                      cnf_save_fs,
                      thy_info,
                      zrxn=zrxn,
                      rid=rid)

    # Build filesys
    cnf_save_fs[1].create([rid])
    inf_obj = autofile.schema.info_objects.conformer_branch(0)

    # Set the samples
    nsamp, tors_range_dct = _calc_nsamp(tors_names, nsamp_par, zma, zrxn=zrxn)
    nsamp0 = nsamp
    nsampd = _calc_nsampd(cnf_save_fs, cnf_run_fs, rid)

    tot_samp = nsamp - nsampd
    brk_tot_samp = nsamp * 5

    ioprinter.info_message(
        ' - Number of samples that have been currently run:', nsampd)
    ioprinter.info_message(' - Number of samples requested:', nsamp)

    if nsamp - nsampd > 0:
        ioprinter.info_message('Running {} samples...'.format(nsamp - nsampd),
                               newline=1)
    samp_idx = 1
    samp_attempt_idx = 1
    while True:
        nsamp = nsamp0 - nsampd
        # Break the while loop if enough sampls completed
        if nsamp <= 0:
            ioprinter.info_message(
                'Requested number of samples have been completed.',
                'Conformer search complete.')
            break
        if samp_attempt_idx == brk_tot_samp:
            ioprinter.info_message(
                'Max sample num: 5*{} attempted, ending search'.format(nsamp),
                'Run again if more samples desired.')
            break

        # Run the conformer sampling
        if nsampd > 0:
            samp_zma, = automol.zmat.samples(zma, 1, tors_range_dct)
        else:
            samp_zma = zma

        bad_geom_count = 0
        geo = automol.zmat.geometry(zma)
        samp_geo = automol.zmat.geometry(samp_zma)
        while (not automol.pot.low_repulsion_struct(geo, samp_geo)
               and bad_geom_count < 1000):
            ioprinter.warning_message('ZMA has high repulsion.', indent=1 / 2.)
            ioprinter.warning_message('Generating new sample ZMA',
                                      indent=1 / 2.,
                                      newline=1)
            samp_zma, = automol.zmat.samples(zma, 1, tors_range_dct)
            samp_geo = automol.zmat.geometry(samp_zma)
            bad_geom_count += 1
        ioprinter.debug_message('ZMA is fine...', indent=1 / 2.)

        cid = autofile.schema.generate_new_conformer_id()
        locs = [rid, cid]

        cnf_run_fs[-1].create(locs)
        cnf_run_path = cnf_run_fs[-1].path(locs)
        run_fs = autofile.fs.run(cnf_run_path)

        ioprinter.info_message("Run {}/{}".format(samp_idx, tot_samp))
        tors_names = tuple(tors_range_dct.keys())
        if two_stage and tors_names:
            frozen_coords_lst = ((), tors_names)
            success, ret = es_runner.multi_stage_optimization(
                script_str=script_str,
                run_fs=run_fs,
                geo=samp_zma,
                spc_info=spc_info,
                thy_info=thy_info,
                frozen_coords_lst=frozen_coords_lst,
                overwrite=overwrite,
                saddle=bool(zrxn is not None),
                retryfail=retryfail,
                **kwargs)
        else:
            success, ret = es_runner.execute_job(job=elstruct.Job.OPTIMIZATION,
                                                 script_str=script_str,
                                                 run_fs=run_fs,
                                                 geo=samp_zma,
                                                 spc_info=spc_info,
                                                 thy_info=thy_info,
                                                 overwrite=overwrite,
                                                 saddle=bool(zrxn is not None),
                                                 retryfail=retryfail,
                                                 **kwargs)

        # save function added here
        if success:
            _save_conformer(ret,
                            cnf_save_fs,
                            locs,
                            thy_info,
                            zrxn=zrxn,
                            orig_ich=spc_info[0],
                            rid_traj=True,
                            init_zma=samp_zma)

            nsampd = _calc_nsampd(cnf_save_fs, cnf_run_fs, rid)
            nsampd += 1
            samp_idx += 1
            inf_obj.nsamp = nsampd
            cnf_save_fs[1].file.info.write(inf_obj, [rid])
            cnf_run_fs[1].file.info.write(inf_obj, [rid])

        # Increment attempt counter
        samp_attempt_idx += 1
Exemple #23
0
def _read_potentials(scan_inf_dct, thy_inf_dct, savefs_dct):
    """ Read values form the filesystem to get the values to
        correct ht MEP
    # Read the energies from the full and constrained opts along MEP
    """

    scn_save_fs = savefs_dct['vscnlvl_scn']
    cscn_save_fs = savefs_dct['vscnlvl_cscn']
    mod_var_scn_thy_info = thy_inf_dct['mod_var_scnlvl']
    mod_var_sp1_thy_info = thy_inf_dct['mod_var_splvl1']
    coord_name = scan_inf_dct['coord_names'][0]
    full_grid = scan_inf_dct['full_grid']
    constraint_dct = scan_inf_dct['constraint_dct']
    grid_val_for_zma = scan_inf_dct['grid_val_for_zma']

    # build objects for loops
    smp_pot, const_pot, sp_pot = [], [], []
    scans = (
        (scn_save_fs, mod_var_scn_thy_info),
        (cscn_save_fs, mod_var_scn_thy_info)
    )
    if mod_var_sp1_thy_info is not None:
        scans += ((scn_save_fs, mod_var_sp1_thy_info),)

    for idx, (scn_fs, thy_info) in enumerate(scans):
        for grid_val in full_grid:
            if idx in (0, 2):
                locs = [[coord_name], [grid_val]]
            else:
                locs = [constraint_dct, [coord_name], [grid_val]]
            sp_ene = filesys.read.energy(scn_fs, locs, thy_info)

            # Store the energy in a lst
            if idx == 0:
                smp_pot.append(sp_ene)
            elif idx == 1:
                const_pot.append(sp_ene)
            elif idx == 2:
                sp_pot.append(sp_ene)
    print('pots test')
    print(smp_pot)
    print(const_pot)
    print(sp_pot)

    sp_corr_inf = (sp_pot[-1] - smp_pot[-1])
    print('inf sp_corr test', sp_corr_inf)

    # Calculate each of the correction potentials
    relax_corr_pot, sp_corr_pot, full_corr_pot = [], [], []
    for i, _ in enumerate(smp_pot):
        # We assume relax_corr_inf = 0
        relax_corr = (smp_pot[i] - const_pot[i]) * phycon.EH2KCAL
        relax_corr_pot.append(relax_corr)
        if all(ene is not None for ene in sp_pot):
            sp_corr = ((sp_pot[i] - smp_pot[i]) - sp_corr_inf) * phycon.EH2KCAL
            sp_corr_pot.append(sp_corr)
        else:
            warning_message("No single point correction applied to potential")
            sp_corr = 0.0
        full_corr_pot.append(relax_corr + sp_corr)

    # Collate the potentials together in a list
    if sp_pot:
        potentials = [relax_corr_pot, sp_corr_pot, full_corr_pot]
        potential_labels = ['relax', 'sp', 'full']
    else:
        potentials = [relax_corr_pot, full_corr_pot]
        potential_labels = ['relax', 'full']

    # Get zma used to make structure.inp and divsur.inp
    inp_zma_locs = [[coord_name], [grid_val_for_zma]]
    if scn_save_fs[-1].file.zmatrix.exists(inp_zma_locs):
        zma_for_inp = scn_save_fs[-1].file.zmatrix.read(inp_zma_locs)
    else:
        zma_for_inp = None

    return potentials, potential_labels, zma_for_inp
Exemple #24
0
def run_tau(zma, spc_info, thy_info,
            tau_run_fs, tau_save_fs, script_str, overwrite,
            nsamp_par=(False, 3, 3, 1, 50, 50),
            tors_names=(),
            repulsion_thresh=40.0,
            zrxn=None, **kwargs):
    """ run sampling algorithm to find tau dependent geometries
    """

    # Set the filesystem objects
    tau_save_fs[0].create()

    # Check if the structure is consistent with the filesystem
    _check_vma(zma, tau_save_fs)

    # Set the samples
    nsamp, tors_range_dct = util.calc_nsamp(
        tors_names, nsamp_par, zma, zrxn=zrxn)
    nsamp0 = nsamp
    nsampd = util.calc_nsampd(tau_save_fs, tau_run_fs, rid=None)

    num_to_samp = nsamp - nsampd

    info_message(
        ' - Number of samples that have been currently run:', nsampd)
    info_message(' - Number of samples requested:', nsamp)

    if num_to_samp > 0:
        info_message(
            f'Running {num_to_samp} samples...', newline=1)
    samp_idx = 1

    # Set the filesystem objects
    inf_obj = autofile.schema.info_objects.tau_trunk(0, tors_range_dct)

    while True:
        nsamp = nsamp0 - nsampd

        # Break the while loop if enough sampls completed
        if nsamp <= 0:
            info_message(
                'Reached requested number of samples. ',
                'Tau sampling complete.')
            break

        samp_zma, = automol.zmat.samples(zma, 1, tors_range_dct)
        tid = autofile.schema.generate_new_tau_id()
        locs = [tid]

        tau_run_fs[-1].create(locs)
        tau_run_prefix = tau_run_fs[-1].path(locs)
        run_fs = autofile.fs.run(tau_run_prefix)

        info_message(f"\nRun {samp_idx}/{num_to_samp}")
        samp_idx += 1

        info_message(
            'Generating sample Z-Matrix that does not have',
            'high intramolecular repulsion...')
        ref_pot = automol.pot.intramol_interaction_potential_sum(
            automol.zmat.geometry(zma))
        samp_pot = automol.pot.intramol_interaction_potential_sum(
            automol.zmat.geometry(samp_zma))
        if samp_pot-ref_pot < repulsion_thresh:
            debug_message('ZMA fine.')
            es_runner.run_job(
                job=elstruct.Job.OPTIMIZATION,
                script_str=script_str,
                run_fs=run_fs,
                geo=samp_zma,
                spc_info=spc_info,
                thy_info=thy_info,
                saddle=bool(zrxn is not None),
                overwrite=overwrite,
                frozen_coordinates=tors_range_dct.keys(),
                **kwargs
            )
        else:
            warning_message('repulsive ZMA:')
            inp_str = elstruct.writer.optimization(
                geo=samp_zma,
                charge=spc_info[1],
                mult=spc_info[2],
                method=thy_info[1],
                basis=thy_info[2],
                prog=thy_info[0],
                orb_type=thy_info[3],
                mol_options=['nosym'],
                frozen_coordinates=tors_range_dct.keys(),
            )
            tau_run_fs[-1].file.geometry_input.write(inp_str, locs)
            warning_message(
                'geometry for bad ZMA at', tau_run_fs[-1].path(locs))

        if tau_save_fs[0].file.info.exists():
            inf_obj_s = tau_save_fs[0].file.info.read()
            nsampd = inf_obj_s.nsamp
        elif tau_run_fs[0].file.info.exists():
            inf_obj_r = tau_run_fs[0].file.info.read()
            nsampd = inf_obj_r.nsamp
        nsampd += 1
        inf_obj.nsamp = nsampd
        tau_save_fs[0].file.info.write(inf_obj)
        tau_run_fs[0].file.info.write(inf_obj)
Exemple #25
0
def tors_projected_freqs(pf_filesystems,
                         mess_hr_str,
                         projrot_hr_str,
                         prefix,
                         zrxn=None,
                         conf=None):
    """ Get frequencies from one version of ProjRot
    """
    run_prefix = pf_filesystems['run_prefix']

    # Build the filesystems
    [harm_cnf_fs, _, harm_min_locs, _, _] = pf_filesystems['harm']
    [tors_cnf_fs, _, tors_min_locs, _, _] = pf_filesystems['tors']
    if conf:
        harm_min_locs = conf[1]
        harm_cnf_fs = conf[2]

    # Read info from the filesystem that is needed
    harm_geo = harm_cnf_fs[-1].file.geometry.read(harm_min_locs)
    hess = harm_cnf_fs[-1].file.hessian.read(harm_min_locs)
    tors_geo = tors_cnf_fs[-1].file.geometry.read(tors_min_locs)
    ioprinter.reading('Hessian', harm_cnf_fs[-1].path(harm_min_locs))

    fml_str = automol.geom.formula_string(harm_geo)
    vib_path = job_path(run_prefix,
                        'PROJROT',
                        'PROJFREQ',
                        fml_str,
                        print_path=True)

    # Read info for the hindered rotors and calculate the ZPVE
    ioprinter.info_message(' - Calculating the torsional ZPVES using MESS...')
    script_str = autorun.SCRIPT_DCT['messpf']
    tors_freqs, _ = autorun.mess.torsions(script_str, vib_path, tors_geo,
                                          mess_hr_str)

    tors_zpe = (sum(tors_freqs) / 2.0) * phycon.WAVEN2EH

    ioprinter.info_message(
        ' - Calculating the RT and RT-rotor projected frequencies ProjRot')

    # NEW projrot writing
    script_str = autorun.SCRIPT_DCT['projrot']
    dist_cutoff_dct1 = {('H', 'O'): 2.26767, ('H', 'C'): 2.26767}
    dist_cutoff_dct2 = {
        ('H', 'O'): 2.83459,
        ('H', 'C'): 2.83459,
        ('C', 'O'): 3.7807
    }
    rotor_dist1_str = projrot_io.writer.projection_distance_aux(
        dist_cutoff_dct=dist_cutoff_dct1)
    rotor_dist2_str = projrot_io.writer.projection_distance_aux(
        dist_cutoff_dct=dist_cutoff_dct2)
    aux_dct1 = {'dist_rotpr.dat': rotor_dist1_str}
    aux_dct2 = {'dist_rotpr.dat': rotor_dist2_str}
    rt_freqs1, rth_freqs1, rt_imag1, _ = autorun.projrot.frequencies(
        script_str,
        vib_path, [harm_geo], [[]], [hess],
        rotors_str=projrot_hr_str,
        aux_dct=aux_dct1)
    _, rth_freqs2, rt_imag2, _ = autorun.projrot.frequencies(
        script_str,
        vib_path, [harm_geo], [[]], [hess],
        rotors_str=projrot_hr_str,
        aux_dct=aux_dct2)

    # Calculate harmonic ZPVE from all harmonic freqs, including torsionals
    harm_zpe = (sum(rt_freqs1) / 2.0) * phycon.WAVEN2EH

    ioprinter.info_message('harmonic zpe is {} kcal/mol'.format(harm_zpe))

    # Calculate harmonic ZPVE from freqs where torsions have been projected out
    # Value from both projrot versions, which use different projection schemes
    harm_zpe_notors_1 = (sum(rth_freqs1) / 2.0) * phycon.WAVEN2EH
    harm_zpe_notors_2 = (sum(rth_freqs2) / 2.0) * phycon.WAVEN2EH

    # Calcuate the difference in the harmonic ZPVE from projecting out torsions
    harm_tors_zpe = harm_zpe - harm_zpe_notors_1
    harm_tors_zpe_2 = harm_zpe - harm_zpe_notors_2

    # Check to see which of the above ZPVEs match more closely with tors ZPVE
    # calculated directly by treating the torsions in MESS
    diff_tors_zpe = harm_tors_zpe - tors_zpe
    diff_tors_zpe_2 = harm_tors_zpe_2 - tors_zpe
    if diff_tors_zpe <= diff_tors_zpe_2:
        freqs = rth_freqs1
        imag_freqs = rt_imag1
        proj_zpe = harm_zpe_notors_1
    else:
        freqs = rth_freqs2
        imag_freqs = rt_imag2
        proj_zpe = harm_zpe_notors_2

    # Check imaginary frequencies and set freqs
    if zrxn is not None:
        if len(imag_freqs) > 1:
            ioprinter.warning_message(
                'There is more than one imaginary frequency')
        imag = max(imag_freqs)
    else:
        imag = None

    # NEW autorun function for the frequencies
    # mess_script_str = autorun.SCRIPT_DCT['messpf']
    # projrot_script_str = autorun.SCRIPT_DCT['projrot']

    # proj_freqs, proj_imags, proj_zpe, harm_freqs, tors_freqs = autorun.projected_frequencies(
    #     mess_script_str, projrot_script_str, vib_path,
    #     mess_hr_str, projrot_hr_str,
    #     tors_geo, harm_geo, hess)
    # if saddle:
    #     proj_imag = proj_imags[0]
    # else:
    #     proj_imag = []

    # NEW scale factor functions
    # scale_factor = automol.prop.freq.rotor_scale_factor_from_harmonics(
    #     harm_freqs, tors_freqs)

    # Create a scaling factor for the frequencies
    # First sort tors frequencies in ascending order
    sort_tors_freqs = sorted(tors_freqs)
    # keep only freqs whose RRHO freqs are above a threshold
    freq_thresh = 50.
    log_rt_freq = 0.0
    nfreq_remove = 0
    for freq in rt_freqs1:
        if freq > freq_thresh:
            log_rt_freq += numpy.log(freq)
        else:
            nfreq_remove += 1

    log_freq = [numpy.log(freq) for freq in freqs]
    log_freq = sum(log_freq)

    log_tors_freq = 0.0
    idx_remove = []
    for idx, freq in enumerate(sort_tors_freqs):
        if idx + 1 > nfreq_remove:
            log_tors_freq += numpy.log(freq)
        else:
            idx_remove.append(tors_freqs.index(freq))

    # log_rt_freq = [numpy.log(freq) for freq in rt_freqs1]
    # log_rt_freq = sum(log_rt_freq)
    # log_tors_freq = [numpy.log(freq) for freq in tors_freqs]
    # log_tors_freq = sum(log_tors_freq)
    #unproj_prod = numpy.prod(rt_freqs1)
    #proj_prod = numpy.prod(freqs) * numpy.prod(tors_freqs)
    #print('proj_prod test:', unproj_prod, proj_prod)
    # ioprinter.info_message('log_freq_tests:', log_rt_freq, log_freq, log_tors_freq)
    #scale_factor = unproj_prod / proj_prod

    # generate the scaling factor
    factor = numpy.exp(log_rt_freq - log_freq - log_tors_freq)
    ioprinter.info_message('freq test:', freqs, tors_freqs, rt_freqs1)
    tau_factor = numpy.exp(log_rt_freq - log_freq)
    tau_factor_mode = tau_factor
    # generate the set of indices for torsions that are two be scales
    scale_factor = (idx_remove, factor)
    ioprinter.info_message('scale fact test', scale_factor)
    ioprinter.info_message('TAU FACTOR {:4.6f} \t {:g} \t {:3.6f} {} '.format(
        tau_factor_mode, len(tors_freqs), factor,
        '-'.join([str(ridx) for ridx in idx_remove])))

    # Check if there are significant differences caused by the rotor projection
    diff_tors_zpe *= phycon.EH2KCAL
    diff_tors_zpe_2 *= phycon.EH2KCAL
    if abs(diff_tors_zpe) > 0.2 and abs(diff_tors_zpe_2) > 0.2:
        ioprinter.warning_message(
            'There is a difference of ',
            '{0:.2f} and {1:.2f}'.format(diff_tors_zpe, diff_tors_zpe_2),
            'kcal/mol between harmonic and hindered torsional ZPVEs')

    return (proj_freqs, proj_imag, proj_zpe, scale_factor, tors_freqs,
            harm_freqs)
Exemple #26
0
def _hrpot_spline_fitter(pot_dct, min_thresh=-0.0001, max_thresh=50.0):
    """ Get a physical hindered rotor potential via a series of spline fits
    """

    pot = list(pot_dct.values())

    # Initialize a variable for the size of the potential
    lpot = len(pot)+1
    pot.append(0.0)

    # Print warning messages
    print_pot = False
    if any(val > max_thresh for val in pot):
        print_pot = True
        max_pot = max(pot)
        ioprinter.warning_message(
            'Found pot val of {0:.2f}'.format(max_pot),
            ' which is larger than',
            'the typical maximum for a torsional potential')
    # reset any negative values for the first grid point to 0.
    if pot[0] < 0.:
        ioprinter.error_message('The first potential value is {} it should be 0.'.format(pot[0]))
        pot[0] = 0.
    if any(val < min_thresh for val in pot):
        print_pot = True
        min_pot = min(pot)
        ioprinter.warning_message(
            'Found pot val of {0:.2f}'.format(min_pot),
            ' which is below',
            '{0} kcal. Refit w/ positives'.format(min_thresh))

    if print_pot:
        ioprinter.debug_message('Potential before spline:', pot)

    # Build a potential list from only successful calculations
    # First replace high potential values with max_thresh
    # Then replace any negative potential values cubic spline fit values
    idx_success = []
    pot_success = []
    for idx in range(lpot):
        if pot[idx] < 600. and pot[idx] > min_thresh:
            idx_success.append(idx)
            if pot[idx] < max_thresh:
                pot_success.append(pot[idx])
            else:
                pot_success.append(max_thresh)

    if len(pot_success) > 3:
        # Build a new potential list using a spline fit of the HR potential
        pot_spl = interp1d(
            numpy.array(idx_success), numpy.array(pot_success), kind='cubic')
        for idx in range(lpot):
            pot[idx] = float(pot_spl(idx))

    # Do second spline fit of only positive values if any negative values found
    if any(val < min_thresh for val in pot):
        ioprinter.warning_message(
            'Still found negative potential values after first spline')
        ioprinter.debug_message('Potential after spline:', pot)
        if len(pot_success) > 3:
            x_pos = numpy.array([i for i in range(lpot)
                                 if pot[i] >= min_thresh])
            y_pos = numpy.array([pot[i] for i in range(lpot)
                                 if pot[i] >= min_thresh])
            pos_pot_spl = interp1d(x_pos, y_pos, kind='cubic')
            pot_pos_fit = []
            for idx in range(lpot):
                pot_pos_fit.append(pos_pot_spl(idx))
        else:
            pot_pos_fit = []
            for idx in range(lpot):
                pot_pos_fit.append(pot[idx])

        ioprinter.debug_message('Potential after spline:', pot_pos_fit)
        # Perform second check to see if negative potentials have been fixed
        if any(val < min_thresh for val in pot_pos_fit):
            ioprinter.warning_message(
                'Still found negative potential values after second spline')
            ioprinter.info_message(
                'Replace with linear interpolation of positive values')
            neg_idxs = [i for i in range(lpot) if pot_pos_fit[i] < min_thresh]
            clean_pot = []
            for i in range(lpot):
                if i in neg_idxs:
                    # Find the indices for positive vals around negative value
                    idx_0 = i - 1
                    while idx_0 in neg_idxs:
                        idx_0 = idx_0 - 1
                    for j in range(i, lpot):
                        if pot_pos_fit[j] >= min_thresh:
                            idx_1 = j
                            break
                    # Get a new value for this point on the potential by
                    # doing a linear interp of positives
                    interp_val = (
                        pot_pos_fit[idx_0] * (1.0-((i-idx_0)/(idx_1-idx_0))) +
                        pot_pos_fit[idx_1] * ((i-idx_0)/(idx_1-idx_0))
                    )
                    clean_pot.append(interp_val)
                else:
                    clean_pot.append(pot_pos_fit[i])
            final_potential = clean_pot.copy()

        else:
            final_potential = pot_pos_fit.copy()

    else:
        final_potential = pot.copy()

    final_potential = final_potential[:-1]

    fin_dct = {}
    for i, val in enumerate(final_potential):
        val_fin = min(val, max_thresh)
        fin_dct[(i,)] = val_fin

    return fin_dct
Exemple #27
0
def inf_sep_ene(ts_dct, thy_inf_dct, thy_method_dct, mref_params, savefs_dct,
                runfs_dct, es_keyword_dct):
    """ Determine the total electronic energy of two reacting species that
        at infinite separation.
    """

    ioprinter.info_message('Calculating the Infinite Separation Energy...')
    ioprinter.info_message('')

    # Get info from the reactants
    rct_info = thy_inf_dct['rct_info']
    overwrite = es_keyword_dct['overwrite']

    # Get thy_inf_dct stuff
    thy_info = thy_inf_dct['runlvl']
    var_scn_thy_info = thy_inf_dct['var_scnlvl']
    var_sp1_thy_info = thy_inf_dct['var_splvl1']
    var_sp2_thy_info = thy_inf_dct['var_splvl2']
    hs_var_sp1_thy_info = thy_inf_dct['hs_var_splvl1']
    hs_var_sp2_thy_info = thy_inf_dct['hs_var_splvl2']
    vscn_method_dct = thy_method_dct['var_scnlvl']
    var_sp1_method_dct = thy_method_dct['var_splvl1']
    var_sp2_method_dct = thy_method_dct['var_splvl2']

    # Get the filesys stuff
    rcts_cnf_fs = savefs_dct['rcts_cnf']
    vscnlvl_scn_run_fs = runfs_dct['vscnlvl_scn']
    vscnlvl_scn_save_fs = savefs_dct['vscnlvl_scn']
    run_prefix = runfs_dct['prefix']

    # Get kwargs for the calculation
    rxn_class = ts_dct['class']
    var = (automol.par.is_radrad(rxn_class)
           and automol.par.is_low_spin(rxn_class))
    if var:
        ts_zma, zrxn = ts_dct['zma'], ts_dct['zrxn']
        rxn_info = ts_dct['rxn_info']

        ts_info = rinfo.ts_info(rxn_info)
        high_mult = rinfo.ts_mult(rxn_info, rxn_mul='high')
        hs_ts_info = (ts_info[0], ts_info[1], high_mult)

        # Build grid and names appropriate for reaction type
        names, _, grids, _ = automol.reac.build_scan_info(zrxn,
                                                          ts_zma,
                                                          var=var)
        inf_locs = (names, (grids[1][-1], ))

        cas_kwargs = mref_params['var_scnlvl']

        _inf_sep_ene = _multiref_inf_sep_ene(hs_ts_info,
                                             ts_zma,
                                             rct_info,
                                             rcts_cnf_fs,
                                             run_prefix,
                                             thy_info,
                                             var_scn_thy_info,
                                             var_sp1_thy_info,
                                             var_sp2_thy_info,
                                             hs_var_sp1_thy_info,
                                             hs_var_sp2_thy_info,
                                             var_sp1_method_dct,
                                             var_sp2_method_dct,
                                             vscnlvl_scn_run_fs,
                                             vscnlvl_scn_save_fs,
                                             inf_locs,
                                             overwrite=overwrite,
                                             **cas_kwargs)
    else:
        vscn_thy_info = thy_inf_dct['var_scnlvl']
        _inf_sep_ene = _singleref_inf_sep_ene(rct_info, thy_info,
                                              vscn_thy_info, rcts_cnf_fs,
                                              run_prefix, vscn_method_dct,
                                              overwrite)

    if _inf_sep_ene is not None:
        ioprinter.energy(_inf_sep_ene)
    else:
        ioprinter.warning_message('Infinite separation ene not computed')

    return _inf_sep_ene
Exemple #28
0
def initial_conformer(spc_dct_i, spc_info, ini_method_dct, method_dct,
                      ini_cnf_save_fs, cnf_run_fs, cnf_save_fs,
                      es_keyword_dct):
    """ Assess if a conformer layer with a geometry exists in the save
        filesys for the given species.

        If not, attempt to generate some guess structure using InChI strings
        or input geom from user.

        and optimize
        it with input method. Then assess if the optimized structure
        corresponds to genuine minimum on the PES via a frequency calculation.

        If a minimum is found, save the conformer geometry, zmatrix, energy,
        and torsions to the save filesys.

        Also, the function assessess if the species is unstable and will
        save the appropriate information.
    """

    ini_thy_info = tinfo.from_dct(ini_method_dct)
    thy_info = tinfo.from_dct(method_dct)
    mod_thy_info = tinfo.modify_orb_label(thy_info, spc_info)
    mod_ini_thy_info = tinfo.modify_orb_label(ini_thy_info, spc_info)
    [kickoff_size, kickoff_backward] = spc_dct_i['kickoff']

    _, cnf_path = filesys.mincnf.min_energy_conformer_locators(
        cnf_save_fs, mod_thy_info)
    overwrite = es_keyword_dct['overwrite']
    if not cnf_path:
        ioprinter.info_message(
            'No conformer found in save filesys. Checking for running jobs...')
        if _init_geom_is_running(cnf_run_fs) and not overwrite:
            _run = False
        else:
            ioprinter.info_message(
                'No conformers are running in run filesys.' +
                'Proceeding with optimization...')
            _run = True
    elif overwrite:
        ioprinter.info_message(
            'User specified to overwrite energy with new run...')
        _run = True
    else:
        _run = False

    if _run:
        ioprinter.info_message('Obtaining some initial guess geometry.')
        geo_init = _obtain_ini_geom(spc_dct_i, ini_cnf_save_fs,
                                    mod_ini_thy_info, overwrite)

        if geo_init is not None:
            ioprinter.debug_message(
                'Assessing if there are any functional groups',
                'that cause instability')
            ioprinter.debug_message('geo str\n', automol.geom.string(geo_init))

            zma_init = automol.geom.zmatrix(geo_init)

            rid = autofile.schema.generate_new_ring_id()
            cid = autofile.schema.generate_new_conformer_id()

            # Determine if there is an instability, if so return prods
            instab_zmas = automol.reac.instability_product_zmas(zma_init)
            if not instab_zmas:

                # Build a cid and a run fs
                cnf_run_fs[-1].create((rid, cid))
                run_fs = autofile.fs.run(cnf_run_fs[-1].path((rid, cid)))

                if not automol.geom.is_atom(geo_init):
                    geo_found = _optimize_molecule(
                        spc_info,
                        zma_init,
                        method_dct,
                        cnf_save_fs, (rid, cid),
                        run_fs,
                        overwrite,
                        kickoff_size=kickoff_size,
                        kickoff_backward=kickoff_backward)
                else:
                    geo_found = _optimize_atom(spc_info, zma_init, method_dct,
                                               cnf_save_fs, (rid, cid), run_fs,
                                               overwrite)
            else:
                ioprinter.info_message(
                    'Found functional groups that cause instabilities')
                filesys.save.instability(zma_init,
                                         instab_zmas,
                                         cnf_save_fs,
                                         rng_locs=(rid, ),
                                         tors_locs=(cid, ),
                                         zma_locs=(0, ))
                geo_found = True
        else:
            geo_found = False
            ioprinter.warning_message(
                'Unable to obtain an initial guess geometry')
    else:
        ioprinter.existing_path('Initial geometry', cnf_path)
        geo_found = True

    return geo_found
Exemple #29
0
def run_vpt2(zma,
             geo,
             spc_info,
             thy_info,
             geo_run_fs,
             geo_save_fs,
             locs,
             run_prefix,
             script_str,
             overwrite,
             zrxn=None,
             retryfail=True,
             method_dct=None,
             ref_val=None,
             **kwargs):
    """ Perform vpt2 analysis for the geometry in the given location
    """

    # Set unneeded vals
    _, _, _, _ = zrxn, method_dct, ref_val, run_prefix

    # Set the run filesystem information
    geo_run_path = geo_run_fs[-1].path(locs)
    geo_save_path = geo_save_fs[-1].path(locs)
    run_fs = autofile.fs.run(geo_run_path)

    # Assess if symmetry needs to be broken for the calculation
    # Add porgram check because might only be issue for gaussian
    if spc_info[0] in symm.HIGH:
        if zma is not None:
            disp = symm.HIGH[spc_info[0]] * phycon.ANG2BOHR
            vals = automol.zmat.value_dictionary(zma)
            job_geo = automol.zmat.set_values_by_name(
                zma, {'R1': vals['R1'] + disp})
            is_atom = automol.geom.is_atom(automol.zmat.geometry(job_geo))
        else:
            ioprinter.warning_message(
                f'Need a zma for high-symmetry of {spc_info[0]}.',
                'Skipping task')
            job_geo = None
            is_atom = False
    else:
        if zma is not None:
            job_geo = zma
            is_atom = automol.geom.is_atom(automol.zmat.geometry(job_geo))
        else:
            job_geo = geo
            is_atom = automol.geom.is_atom(job_geo)

    if is_atom:
        ioprinter.info_message('Species is an atom, Skipping VPT2 task.')

    if job_geo is not None and not is_atom:

        exists = geo_save_fs[-1].file.anharmonicity_matrix.exists(locs)
        if not exists:
            ioprinter.info_message(
                'No X-Matrix found in save filesys. Running VPT2...')
            _run = True
        elif overwrite:
            ioprinter.info_message(
                'User specified to overwrite VPT2 info with new run...')
            _run = True
        else:
            _run = False

        if _run:

            success, ret = es_runner.execute_job(
                job=elstruct.Job.VPT2,
                script_str=script_str,
                run_fs=run_fs,
                geo=job_geo,
                spc_info=spc_info,
                thy_info=thy_info,
                zrxn=zrxn,
                overwrite=overwrite,
                retryfail=retryfail,
                **kwargs,
            )

            if success:
                inf_obj, inp_str, out_str = ret

                ioprinter.info_message(
                    " - Reading anharmonicities from output...")
                vpt2_dct = elstruct.reader.vpt2(inf_obj.prog, out_str)

                ioprinter.save_anharmonicity(geo_save_path)
                geo_save_fs[-1].file.vpt2_input.write(inp_str, locs)
                geo_save_fs[-1].file.anharmonic_frequencies.write(
                    vpt2_dct['freqs'], locs)
                geo_save_fs[-1].file.anharmonic_zpve.write(
                    vpt2_dct['zpve'], locs)
                geo_save_fs[-1].file.vibro_rot_alpha_matrix.write(
                    vpt2_dct['vibrot_mat'], locs)
                geo_save_fs[-1].file.quartic_centrifugal_dist_consts.write(
                    vpt2_dct['cent_dist_const'], locs)
                geo_save_fs[-1].file.anharmonicity_matrix.write(
                    vpt2_dct['x_mat'], locs)
                geo_save_fs[-1].file.cubic_force_constants.write(
                    vpt2_dct['cubic_fc'], locs)
                geo_save_fs[-1].file.quartic_force_constants.write(
                    vpt2_dct['quartic_fc'], locs)

        else:
            ioprinter.existing_path('VPT2 information', geo_save_path)
Exemple #30
0
def _optimize_molecule(spc_info,
                       zma_init,
                       method_dct,
                       cnf_save_fs,
                       locs,
                       run_fs,
                       overwrite,
                       kickoff_size=0.1,
                       kickoff_backward=False):
    """ Optimize a proper geometry
    """
    thy_info = tinfo.from_dct(method_dct)
    mod_thy_info = tinfo.modify_orb_label(thy_info, spc_info)
    script_str, kwargs = es_runner.qchem_params(method_dct,
                                                job=elstruct.Job.OPTIMIZATION)

    # Call the electronic structure optimizer
    success, ret = es_runner.execute_job(job=elstruct.Job.OPTIMIZATION,
                                         script_str=script_str,
                                         run_fs=run_fs,
                                         geo=zma_init,
                                         spc_info=spc_info,
                                         thy_info=mod_thy_info,
                                         overwrite=overwrite,
                                         **kwargs)

    # read the geometry
    if success:
        inf_obj, _, out_str = ret
        geo = elstruct.reader.opt_geometry(inf_obj.prog, out_str)
        zma = elstruct.reader.opt_zmatrix(inf_obj.prog, out_str)
        if zma is None:
            zma = automol.geom.zmatrix(geo)
        geo_conn = bool(automol.geom.connected(geo))

    # If connected, check for imaginary modes and fix them if possible
    if geo_conn:

        # Remove the imaginary mode
        geo, ret = remove_imag(geo,
                               ret,
                               spc_info,
                               method_dct,
                               run_fs,
                               kickoff_size,
                               kickoff_backward,
                               kickoff_mode=0,
                               overwrite=overwrite)

        # Recheck connectivity for imag-checked geometry
        if geo is not None:
            conf_found = True
            if automol.geom.connected(geo):
                ioprinter.info_message(
                    'Saving structure as the first conformer...', newline=1)
                filesys.save.conformer(ret,
                                       None,
                                       cnf_save_fs,
                                       mod_thy_info[1:],
                                       rng_locs=(locs[0], ),
                                       tors_locs=(locs[1], ))
            else:
                ioprinter.info_message('Saving disconnected species...')
                filesys.save.instability(zma_init,
                                         zma,
                                         cnf_save_fs,
                                         rng_locs=(locs[0], ),
                                         tors_locs=(locs[1], ),
                                         zma_locs=(0, ))
        else:
            ioprinter.warning_message('No geom found...', newline=1)
            conf_found = False
    else:
        ioprinter.info_message('Saving disconnected species...')
        conf_found = False
        filesys.save.instability(zma_init,
                                 zma,
                                 cnf_save_fs,
                                 rng_locs=(locs[0], ),
                                 tors_locs=(locs[1], ),
                                 zma_locs=(0, ))

    return conf_found