Ejemplo n.º 1
0
def load_input_file(path):
    """
    Load the Arkane input file located at `path` on disk, and return a list of
    the jobs defined in that file.
    """
    global species_dict, transition_state_dict, reaction_dict, network_dict, job_list

    # Clear module-level variables
    species_dict, transition_state_dict, reaction_dict, network_dict = dict(
    ), dict(), dict(), dict()
    job_list = []

    global_context = {'__builtins__': None}
    local_context = {
        '__builtins__': None,
        'True': True,
        'False': False,
        'range': range,
        # Collision
        'TransportData': TransportData,
        'SingleExponentialDown': SingleExponentialDown,
        # Kinetics
        'Arrhenius': Arrhenius,
        'RateUncertainty': RateUncertainty,
        # Statistical mechanics
        'IdealGasTranslation': IdealGasTranslation,
        'LinearRotor': LinearRotor,
        'NonlinearRotor': NonlinearRotor,
        'KRotor': KRotor,
        'SphericalTopRotor': SphericalTopRotor,
        'HarmonicOscillator': HarmonicOscillator,
        'HinderedRotor': HinderedRotor,
        'FreeRotor': FreeRotor,
        # Thermo
        'ThermoData': ThermoData,
        'Wilhoit': Wilhoit,
        'NASA': NASA,
        'NASAPolynomial': NASAPolynomial,
        # Functions
        'reaction': reaction,
        'species': species,
        'transitionState': transitionState,
        'network': network,
        'database': database,
        # Jobs
        'kinetics': kinetics,
        'statmech': statmech,
        'thermo': thermo,
        'pressureDependence': pressureDependence,
        'explorer': explorer,
        'bac': bac,
        'ae': ae,
        # Miscellaneous
        'SMILES': SMILES,
        'adjacencyList': adjacencyList,
        'InChI': InChI,
        'LevelOfTheory': LevelOfTheory,
        'CompositeLevelOfTheory': CompositeLevelOfTheory,
    }

    load_necessary_databases()

    with open(path, 'r') as f:
        try:
            exec(f.read(), global_context, local_context)
        except (NameError, TypeError, SyntaxError):
            logging.error('The input file {0!r} was invalid:'.format(path))
            raise

    model_chemistry = local_context.get('modelChemistry', None)
    level_of_theory = process_model_chemistry(model_chemistry)
    if isinstance(model_chemistry, LOT):
        model_chemistry = model_chemistry.to_model_chem()

    author = local_context.get('author', '')
    if 'frequencyScaleFactor' in local_context:
        frequency_scale_factor = local_context.get('frequencyScaleFactor')
    else:
        logging.debug(
            'Tying to assign a frequencyScaleFactor according to the '
            'level of theory {0}'.format(level_of_theory))
        frequency_scale_factor = assign_frequency_scale_factor(level_of_theory)
    use_hindered_rotors = local_context.get('useHinderedRotors', True)
    use_atom_corrections = local_context.get('useAtomCorrections', True)
    use_bond_corrections = local_context.get('useBondCorrections', False)
    bac_type = local_context.get('bondCorrectionType', 'p')
    use_isodesmic_reactions = local_context.get('useIsodesmicReactions', False)
    reference_sets = local_context.get('referenceSets', None)
    atom_energies = local_context.get('atomEnergies', None)

    directory = os.path.dirname(path)

    for rxn in reaction_dict.values():
        rxn.elementary_high_p = True

    for job in job_list:
        if isinstance(job, StatMechJob):
            job.path = os.path.join(directory, job.path)
            job.level_of_theory = level_of_theory
            job.frequencyScaleFactor = frequency_scale_factor
            job.includeHinderedRotors = use_hindered_rotors
            job.applyAtomEnergyCorrections = use_atom_corrections
            job.applyBondEnergyCorrections = use_bond_corrections
            job.bondEnergyCorrectionType = bac_type
            job.atomEnergies = atom_energies
            job.useIsodesmicReactions = use_isodesmic_reactions
            job.referenceSets = reference_sets
        if isinstance(job, ThermoJob):
            job.arkane_species.author = author
            job.arkane_species.level_of_theory = level_of_theory
            job.arkane_species.model_chemistry = model_chemistry
            job.arkane_species.frequency_scale_factor = frequency_scale_factor
            job.arkane_species.use_hindered_rotors = use_hindered_rotors
            job.arkane_species.use_bond_corrections = use_bond_corrections
            if atom_energies is not None:
                job.arkane_species.atom_energies = atom_energies

    return job_list, reaction_dict, species_dict, transition_state_dict, network_dict, level_of_theory
Ejemplo n.º 2
0
    def to_arkane_level_of_theory(
        self,
        variant: Optional[str] = None,
        bac_type: str = 'p',
        comprehensive: bool = False,
        raise_error: bool = False,
        warn: bool = True,
    ) -> Optional[LevelOfTheory]:
        """
        Convert ``Level`` to an Arkane ``LevelOfTheory`` instance.

        Args:
            variant (str, optional): Return a variant of the Arkane ``LevelOfTheory`` that matches an Arkane query.
                                     Allowed values are ``'freq'``, ``'AEC'``, ``'BEC'``. Returns ``None`` if no
                                     functioning variant was found.
            bac_type (str, optional): The BAC type ('p' or 'm') to use when searching for a ``LevelOfTheory`` variant
                                      for BAC.
            comprehensive (bool, optional): Whether to consider all relevant arguments if not looking for a variant.
            raise_error (bool, optional): Whether to raise an error if an AEC variant could not be found.
            warn (bool, optional): Whether to output a warning if an AEC variant could not be found.

        Returns:
            LevelOfTheory: The respective Arkane ``LevelOfTheory`` object
        """
        if variant is None:
            if not comprehensive:
                # only add basis and software if needed
                kwargs = {'method': self.method}
                if self.basis is not None:
                    kwargs['basis'] = self.basis
                kwargs['software'] = self.software
                return LevelOfTheory(**kwargs)
            else:
                # consider all relevant arguments
                kwargs = self.__dict__.copy()
                del kwargs['solvation_scheme_level']
                del kwargs['method_type']
                del kwargs['repr']
                del kwargs['compatible_ess']
                del kwargs['dispersion']
                del kwargs['args']
                if self.args is not None and self.args and all(
                    [val for val in self.args.values()]):
                    # only pass keyword arguments to Arkane (not blocks)
                    if any([key == 'keyword' for key in self.args.keys()]):
                        kwargs['args'] = list()
                        for key1, val1 in self.args.items():
                            if key1 == 'keyword':
                                for val2 in val1.values():
                                    kwargs['args'].append(val2)
                                break
                    else:
                        kwargs['args'] = None
                if self.dispersion is not None:
                    if 'args' not in kwargs:
                        kwargs['args'] = [self.dispersion]
                    else:
                        kwargs['args'].append(self.dispersion)
                if kwargs['method'] is not None:
                    kwargs['method'].replace('f12a',
                                             'f12').replace('f12b', 'f12')
                if kwargs['basis'] is not None:
                    kwargs['basis'].replace('f12a',
                                            'f12').replace('f12b', 'f12')
                return LevelOfTheory(**kwargs)
        else:
            # search for a functioning variant
            if variant not in ['freq', 'AEC', 'BAC']:
                raise ValueError(
                    f'variant must be either "freq", "AEC", or "BAC", got "{variant}".'
                )
            kwargs = {'method': self.method}
            if self.basis is not None:
                kwargs['basis'] = self.basis
            if standardize_name(self.method) in METHODS_THAT_REQUIRE_SOFTWARE:
                # add software if mandatory (otherwise, Arkane won't accept this object initialization)
                kwargs['software'] = self.software
            var_2 = LevelOfTheory(**kwargs)
            kwargs['software'] = self.software  # add or overwrite software
            # start w/ the software argument (var_1) in case there are several entries that only vary by software
            var_1 = LevelOfTheory(**kwargs)

            if variant == 'freq':
                # if not found, the factor is set to exactly 1
                if assign_frequency_scale_factor(level_of_theory=var_1) != 1:
                    return var_1
                if assign_frequency_scale_factor(level_of_theory=var_2) != 1:
                    return var_2
                return None

            if variant == 'AEC':
                try:
                    arkane_data.atom_energies[var_1]
                    return var_1
                except KeyError:
                    try:
                        arkane_data.atom_energies[var_2]
                        return var_2
                    except KeyError:
                        if raise_error:
                            raise ValueError(
                                f'Missing Arkane atom energy corrections for {var_1}\n'
                                f'(If you did not mean to compute thermo, set the compute_thermo '
                                f'argument to False to avoid this error.)')
                        else:
                            if warn:
                                logger.warning(
                                    f'Missing Arkane atom energy corrections for {var_1}.'
                                )
                            return None

            if variant == 'BAC':
                if bac_type not in ['p', 'm']:
                    raise ValueError(
                        f'bac_type must be either "p" or "m", got "{bac_type}".'
                    )
                bac = BAC(level_of_theory=var_1, bac_type=bac_type)
                if bac.bacs is None:
                    bac = BAC(level_of_theory=var_2, bac_type=bac_type)
                    if bac.bacs is None:
                        logger.warning(f'Missing Arkane BAC for {var_2}.')
                        return None
                    else:
                        return var_2
                else:
                    return var_1
Ejemplo n.º 3
0
 def freq_scale_factor(self):
     if not self._freq_scale_factor:
         self._freq_scale_factor = assign_frequency_scale_factor(
             self.model_chemistry)
     return self._freq_scale_factor