uclchem.utils ============= .. py:module:: uclchem.utils .. autoapi-nested-parse:: Helper functions and utilities for UCLCHEM operations. This module provides utility functions for: - Error handling and reporting - Physics calculations (shock dissipation times) - Parameter validation - File path management **Key Functions:** - :meth:`SuccessFlag.check_error` - Convert UCLCHEM error codes to messages - :func:`cshock_dissipation_time` - Calculate C-shock dissipation timescale **Example Usage:** >>> import uclchem >>> >>> model = uclchem.model.Cloud({}) >>> success_flag = model.success_flag >>> >>> # Check error from model run >>> success_flag.check_error() Model ran successfully >>> >>> # Only print if an error occurred >>> success_flag.check_error(only_error=True) >>> # Calculate shock timescale >>> t_diss = uclchem.utils.cshock_dissipation_time( ... shock_vel=50.0, # km/s ... initial_dens=1e4, # cm^-3 ... ) >>> print(f"Dissipation time: {t_diss:.1e} years") # doctest: +ELLIPSIS Dissipation time: ... years **Error Codes:** UCLCHEM model functions return :class:`SuccessFlag` instances: - ``-1``: Parameter read failed (misspelled parameter) - ``-2``: Physics initialization failed (invalid parameters) - ``-3``: Chemistry initialization failed - ``-4``: Integrator error (DVODE failed) and more... Use :meth:`SuccessFlag.check_error` to get human-readable error messages. **See Also:** - :mod:`uclchem.model` - Model classes that use these utilities Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: uclchem.utils.CollapseMode uclchem.utils.SuccessFlag uclchem.utils.TempMode Functions ~~~~~~~~~ .. autoapisummary:: uclchem.utils.collapse_radial_velocity uclchem.utils.configure_logging uclchem.utils.cshock_dissipation_time uclchem.utils.find_number_of_consecutive_digits uclchem.utils.get_collapse_mode uclchem.utils.get_dtype uclchem.utils.get_protostellar_Teff uclchem.utils.get_protostellar_model_index uclchem.utils.get_reaction_table uclchem.utils.get_species uclchem.utils.get_species_table Attributes ~~~~~~~~~~ .. autoapisummary:: uclchem.utils.L_SUN uclchem.utils.MISSING_VALUE_FLOAT uclchem.utils.MISSING_VALUE_INTEGER uclchem.utils.NO_REACTANT_OR_PRODUCT uclchem.utils.UCLCHEM_ROOT_DIR .. py:class:: CollapseMode Bases: :py:obj:`enum.IntEnum` Collapse mode. Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: AMBIPOLAR :value: 4 .. py:attribute:: BE1_1 :value: 1 .. py:attribute:: BE4 :value: 2 .. py:attribute:: FILAMENT :value: 3 .. py:class:: SuccessFlag Bases: :py:obj:`enum.IntEnum` SuccessFlag indicates whether the model failed or ran successfully,. and if it failed how. Initialize self. See help(type(self)) for accurate signature. .. py:method:: check_error(only_error: bool = False, raise_on_error: bool = True) -> str | None Convert the UCLCHEM integer result flag to a message explaining what went wrong. :param only_error: If True, skip printing if the model ran successfully, and only error out if it did not. Default = False. :type only_error: bool :param raise_on_error: If True, raises RuntimeError if the `self` is not `SuccessFlag.SUCCESS`. If False, returns the message string. Default = True. :type raise_on_error: bool :returns: Error message, or ``None`` if the model ran successfully. :rtype: str | None :raises RuntimeError: If `raise_on_error` is True. .. py:attribute:: CHEM_INIT_ERROR .. py:attribute:: CONSERVATION_ERROR .. py:attribute:: COOLANT_CONFIG_ERROR .. py:attribute:: COOLANT_DATA_ERROR .. py:attribute:: COOLANT_FILE_ERROR .. py:attribute:: COOLANT_FREQ_TOL_ERROR .. py:attribute:: COOLANT_POP_TOL_ERROR .. py:attribute:: COOLANT_SOLVER_ERROR .. py:attribute:: INT_TOO_MANY_FAILS_ERROR .. py:attribute:: INT_UNRECOVERABLE_ERROR .. py:attribute:: NEGATIVE_ABUNDANCE_ERROR .. py:attribute:: NOT_ENOUGH_TIMEPOINTS_ERROR .. py:attribute:: PARAMETER_READ_ERROR .. py:attribute:: PHYSICS_INIT_ERROR .. py:attribute:: PHYSICS_UPDATE_ERROR .. py:attribute:: SOLVER_STATS_OVERFLOW_ERROR .. py:attribute:: SUCCESS :value: (0, 'Model ran successfully') .. py:attribute:: ZERO_INNER_RADIUS_ERROR .. py:class:: TempMode(*args, **kwds) Bases: :py:obj:`enum.Enum` Interpolation scheme for :func:`get_protostellar_Teff`. .. py:attribute:: BINS :value: 'bins' .. py:attribute:: SMOOTH :value: 'smooth' .. py:attribute:: SMOOTH_CUSTOM :value: 'smooth_custom' .. py:attribute:: SMOOTH_HIGH :value: 'smooth_high' .. py:attribute:: SMOOTH_LOW :value: 'smooth_low' .. py:function:: collapse_radial_velocity(model: uclchem.model.Collapse, point: int = 0) -> pandas.Series Return the radial velocity (cm/s) for a parcel of a Collapse model. For filament (mode 3) and ambipolar (mode 4) collapse modes, uses the analytical radial-velocity fit functions from Priestley et al. (2018). For BE1.1 and BE4 modes (1 & 2), the radius is tracked via mass-conservation integration in Fortran, not a velocity fit. The radial velocity is therefore a finite-difference approximation of parcel_radius — it is NOT the relationship used to generate the model and should be treated as an estimate only. :param model: A successfully run :class:`~uclchem.model.Collapse` instance. :type model: Collapse :param point: Parcel index (0-based). Defaults to 0. :type point: int :returns: Radial velocity in cm s⁻¹, indexed by time in years. Negative values indicate infall. :rtype: pd.Series :raises TypeError: If *model* is not a Collapse model instance. :raises TypeError: If ``model.collapse`` is not an instance of class:`CollapseMode`. .. py:function:: configure_logging(level: str = 'WARNING', stream: None | str | Any = None) -> None Configure the ``uclchem`` logger. :param level: Logging level name (e.g. ``"DEBUG"``, ``"WARNING"``). Default ``"WARNING"``. :type level: str :param stream: Where to send log output. ``None`` suppresses all output (no handlers, propagation disabled). A string is treated as a file path and a ``FileHandler`` is added. Any other value (e.g. ``sys.stdout``) is wrapped in a ``StreamHandler``. Defaults to ``None``. :type stream: None | str | Any .. py:function:: cshock_dissipation_time(shock_vel: float, initial_dens: float) -> float Calculate the dissipation time of a C-type shock. Use to obtain a useful timescale for your C-shock model runs. Velocity of ions and neutrals equalizes at dissipation time and full cooling takes a few dissipation times. :param shock_vel: Velocity of the shock in km/s :type shock_vel: float :param initial_dens: Preshock density of the gas in cm$^{-3}$ :type initial_dens: float :returns: The dissipation time of the shock in years :rtype: float .. py:function:: find_number_of_consecutive_digits(string: str, start: int) -> int Determine the number of consecutive digits in a string, starting. from some index `start`. :param string: the string :type string: str :param start: the starting index :type start: int :returns: **num_digits** -- the number of consecutive digits in the string starting from "start". :rtype: int .. rubric:: Examples >>> find_number_of_consecutive_digits("Hello123", 0) 0 >>> find_number_of_consecutive_digits("Hello123", 5) 3 >>> find_number_of_consecutive_digits("Hello123", 6) 2 >>> find_number_of_consecutive_digits("He1llo23", 2) 1 .. py:function:: get_collapse_mode(mode: str | int | CollapseMode) -> CollapseMode Get the CollapseMode instance. Integers are converted to the CollapseMode, CollapseMode instances are returned unchanged, and strings are converted according to the names of the different modes. :param mode: Collapse mode. :type mode: str | int | CollapseMode :returns: collapse mode Enum :rtype: CollapseMode :raises TypeError: If ``mode`` is not a string, integer or :class:`CollapseMode`. :raises ValueError: If ``mode`` is a string, but not one of ``["BE1.1", "BE4", "filament", "ambipolar"]`` (case insensitive). .. py:function:: get_dtype(dtype: str | type | numpy.dtype) -> type | numpy.dtype Convert a dtype shorthand string or numpy dtype to a numpy dtype. :param dtype: Either a shorthand string ("fp64", "fp32", "fp16") or a numpy dtype/type. :type dtype: str | type | np.dtype :returns: The corresponding numpy dtype or type. :rtype: type | np.dtype :raises ValueError: If ``dtype`` is a string not in ``{"fp64", "fp32", "fp16"}``. .. py:function:: get_protostellar_Teff(L_star: float, *, mode: TempMode = TempMode.BINS, custom_T0: float | None = None, custom_alpha: float | None = None, L_star_unit: str = 'L_sun') -> float Return the effective temperature [K] for a protostellar object. :param L_star: Stellar luminosity. Valid range depends on *mode*; see :data:`_RANGES`. :type L_star: float :param mode: Interpolation scheme: - :attr:`TempMode.SMOOTH` (default) — global power-law fit to all seven bins, valid 1 – 1e6 L_sun. - :attr:`TempMode.BINS` — discrete stepwise lookup, valid 1 – 1e6 L_sun. - :attr:`TempMode.SMOOTH_LOW` — power-law fit to bins 1–3, valid 1 – 1e4 L_sun. - :attr:`TempMode.SMOOTH_HIGH` — power-law fit to bins 4–7, valid 1e3 – 1e6 L_sun. Defaults to ``TempMode.BINS``. :type mode: TempMode :param custom_T0: Temperature constant T0 in the power-law fit T = T0 * L^alpha, used only when mode is ``TempMode.SMOOTH_CUSTOM``. Defaults to ``None``. :type custom_T0: float | None :param custom_alpha: Power-law exponent alpha in T = T0 * L^alpha, used only when mode is ``TempMode.SMOOTH_CUSTOM``. Defaults to ``None``. :type custom_alpha: float | None :param L_star_unit: Unit of ``L_star``. Either ``'L_sun'`` or ``'W'``. Defaults to ``'L_sun'``. :type L_star_unit: str :returns: Effective temperature in Kelvin. :rtype: float :raises TypeError: If ``L_star`` is not a real number. :raises ValueError: If ``L_star`` is outside the valid range for the chosen mode, or if custom fit parameters are provided but mode is not ``TempMode.SMOOTH_CUSTOM``. :raises RuntimeError: If no bin matches ``L_star`` in ``TempMode.BINS`` mode (indicates a bug). .. rubric:: Examples >>> get_protostellar_Teff(1.0, mode=TempMode.SMOOTH) # 1 L_sun, smooth 4788.72 >>> get_protostellar_Teff(1000.0, mode=TempMode.BINS) # 1000 L_sun, bins 20000.0 .. py:function:: get_protostellar_model_index(L_star: float) -> int Obtain the right model index for protostellar core models in 1D mode based on the. stellar luminosity :param L_star: Stellar luminosity in units of solar luminosity (L_sun) :type L_star: float :returns: The model index for the protostellar core model. :rtype: int :raises ValueError: If the stellar luminosity is below the minimum valid value. .. py:function:: get_reaction_table(file: str | pathlib.Path | None = None) -> pandas.DataFrame Load the reaction table from the UCLCHEM network into a pandas dataframe. :param file: Path to the reactions CSV file. If None, uses ``UCLCHEM_ROOT_DIR / "reactions.csv"``. Default = None. :type file: str | Path | None :returns: **reactions** -- A dataframe containing the reactions and their rates :rtype: pd.DataFrame .. py:function:: get_species(file: str | pathlib.Path | None = None) -> list[str] Load the list of species present in the UCLCHEM network. :param file: Path to the species CSV file. If None, uses ``UCLCHEM_ROOT_DIR / "species.csv"``. Default = None. :type file: str | Path | None :returns: **species_list** -- A list of species names :rtype: list[str] .. py:function:: get_species_table(file: str | pathlib.Path | None = None) -> pandas.DataFrame Load the list of species in the UCLCHEM network into a pandas dataframe. :param file: Path to the species CSV file. If None, uses ``UCLCHEM_ROOT_DIR / "species.csv"``. Default = None. :type file: str | Path | None :returns: **species** -- A dataframe containing the species names and their details :rtype: pd.DataFrame .. py:data:: L_SUN :type: float :value: 3.828e+26 .. py:data:: MISSING_VALUE_FLOAT :type: float :value: -1.0 Float to indicate a missing value .. py:data:: MISSING_VALUE_INTEGER :type: int :value: -1 Integer to indicate a missing value .. py:data:: NO_REACTANT_OR_PRODUCT :type: int :value: 9999 Integer to indicate that there is no reactant or product. .. py:data:: UCLCHEM_ROOT_DIR :type: pathlib.Path UCLCHEM root directory