Source code for hermes_rheo.lve_models.protocols

"""Simulated rheometer protocols.

:class:`Protocols` runs SAOS, creep and stress relaxation on any
:class:`~hermes_rheo.lve_models.base.LVEModel` and returns piblin objects that
feed directly into hermes-rheo transforms.

Examples
--------
>>> import numpy as np
>>> from hermes_rheo.lve_models import MaxwellModel, Protocols
>>> model = MaxwellModel(G=1e5, tau=1.0)
>>> meas = Protocols.saos(model, np.geomspace(1e-2, 1e2, 50))
>>> meas.datasets[0].data_array_names[:3]
['angular frequency', 'storage modulus', 'loss modulus']
"""

from __future__ import annotations

from collections.abc import Sequence
from typing import Any

import numpy as np
from piblin.data.data_collections import experiment_set as _experiment_set
from piblin.data.data_collections import measurement as _measurement
from piblin.data.data_collections import measurement_set as _measurement_set

from hermes_rheo.lve_models.base import LVEModel

__all__ = ["Protocols"]


[docs] class Protocols: """Simulated experiments on an LVE model. All methods are static."""
[docs] @staticmethod def saos(model: LVEModel, omega: np.ndarray, **kwargs: Any) -> _measurement.Measurement: """Small-amplitude oscillatory shear. *omega* in rad/s.""" return model.to_measurement("saos", omega, **kwargs)
[docs] @staticmethod def creep(model: LVEModel, t: np.ndarray, **kwargs: Any) -> _measurement.Measurement: """Creep compliance. *t* in s.""" return model.to_measurement("creep", t, **kwargs)
[docs] @staticmethod def stress_relaxation( model: LVEModel, t: np.ndarray, **kwargs: Any ) -> _measurement.Measurement: """Stress relaxation modulus. *t* in s.""" return model.to_measurement("stress_relaxation", t, **kwargs)
[docs] @staticmethod def experiment_set( model: LVEModel, protocols: Sequence[dict[str, Any]], ) -> _experiment_set.ExperimentSet | _measurement_set.MeasurementSet: """Run several protocols on one model. Parameters ---------- model : LVEModel protocols : sequence of dict Each dict has ``"protocol"`` (``"saos"``, ``"creep"`` or ``"stress_relaxation"``) and ``"x"`` (the grid), plus optional ``"conditions"`` and ``"details"``. Returns ------- ExperimentSet or MeasurementSet An ``ExperimentSet`` when piblin can group the measurements, otherwise a ``MeasurementSet``. """ if not protocols: raise ValueError("protocols must contain at least one entry") measurements = [] for i, entry in enumerate(protocols): if "protocol" not in entry or "x" not in entry: raise ValueError(f"protocols[{i}] needs 'protocol' and 'x', got {entry!r}") measurements.append(model.to_measurement(**entry)) try: return _experiment_set.ExperimentSet(measurements=measurements, merge_redundant=False) except Exception: return _measurement_set.MeasurementSet(measurements=measurements)