> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/atomind-ai/mlip-arena/llms.txt
> Use this file to discover all available pages before exploring further.

# Equation of state

> Compute the energy-volume curve and fit a Birch-Murnaghan EOS to extract bulk modulus and equilibrium volume.

The `EOS` task calculates the equation of state (EOS) for a crystal. It:

1. Fully relaxes the input structure (positions + cell) using `OPT`.
2. Generates `npoints` uniformly strained copies of the relaxed cell spanning `±max_abs_strain`.
3. Relaxes atomic positions inside each strained cell (cell shape fixed).
4. Fits a Birch-Murnaghan EOS to the resulting energy-volume data.

All per-strain optimizations can be dispatched concurrently via Prefect.

## Function signature

```python theme={null}
from mlip_arena.tasks import EOS

result = EOS(
    atoms=atoms,
    calculator=calc,
    optimizer="BFGSLineSearch",
    optimizer_kwargs=None,
    filter="FrechetCell",
    filter_kwargs=None,
    criterion=None,
    max_abs_strain=0.1,
    npoints=11,
    concurrent=True,
    cache_opt=False,
)
```

## Parameters

<ParamField path="body.atoms" type="ase.Atoms" required>
  Input structure. A copy is made internally.
</ParamField>

<ParamField path="body.calculator" type="ase.calculators.calculator.BaseCalculator" required>
  ASE calculator for energies and forces.
</ParamField>

<ParamField path="body.optimizer" type="Optimizer | str" default="BFGSLineSearch">
  Optimizer passed to the internal `OPT` tasks. See [structure optimization](/tasks/structure-optimization) for valid values.
</ParamField>

<ParamField path="body.optimizer_kwargs" type="dict | None" default="None">
  Extra keyword arguments forwarded to the optimizer.
</ParamField>

<ParamField path="body.filter" type="Filter | str | None" default="FrechetCell">
  Cell filter used for the initial full relaxation. Set to `None` to skip cell relaxation.
</ParamField>

<ParamField path="body.filter_kwargs" type="dict | None" default="None">
  Extra keyword arguments forwarded to the filter.
</ParamField>

<ParamField path="body.criterion" type="dict | None" default="None">
  Convergence criterion dict forwarded to each `OPT` run (e.g. `{"fmax": 0.01}`).
</ParamField>

<ParamField path="body.max_abs_strain" type="number" default="0.1">
  Maximum absolute volumetric strain applied to the equilibrium cell. A value of `0.1` spans cell scale factors from `0.9^(1/3)` to `1.1^(1/3)` along each axis.
</ParamField>

<ParamField path="body.npoints" type="number" default="11">
  Number of volume points sampled along the strain range, including the endpoints.
</ParamField>

<ParamField path="body.concurrent" type="boolean" default="true">
  If `True`, all per-strain `OPT` tasks are submitted concurrently using `OPT.submit()` and collected with `prefect.futures.wait`. Set to `False` for serial execution.
</ParamField>

<ParamField path="body.cache_opt" type="boolean" default="false">
  If `True`, intermediate `OPT` results are persisted and cached in Prefect's result store. Useful when re-running the EOS with the same structure.
</ParamField>

## Return value

Returns a `dict` with the following keys on success, or a Prefect `State` object if the initial relaxation fails:

| Key     | Type        | Description                                                             |
| ------- | ----------- | ----------------------------------------------------------------------- |
| `atoms` | `ase.Atoms` | Fully relaxed equilibrium structure                                     |
| `eos`   | `dict`      | `{"volumes": [...], "energies": [...]}` — raw E-V data sorted by volume |
| `K`     | `float`     | Bulk modulus in GPa (Birch-Murnaghan `B0`)                              |
| `b0`    | `float`     | Bulk modulus in eV/Å³                                                   |
| `b1`    | `float`     | Pressure derivative of the bulk modulus                                 |
| `e0`    | `float`     | Equilibrium energy in eV                                                |
| `v0`    | `float`     | Equilibrium volume in Å³                                                |

## Example

<Steps>
  <Step title="Import and prepare">
    ```python theme={null}
    from ase.build import bulk
    from mlip_arena.tasks import EOS
    from mlip_arena.tasks.utils import get_calculator
    from mlip_arena.models import MLIPEnum

    atoms = bulk("Si", "diamond", a=5.43)
    calc = get_calculator(MLIPEnum.MACE_MP)
    ```
  </Step>

  <Step title="Run the EOS task">
    ```python theme={null}
    result = EOS(
        atoms=atoms,
        calculator=calc,
        max_abs_strain=0.1,
        npoints=11,
        criterion={"fmax": 0.01},
    )
    ```
  </Step>

  <Step title="Inspect results">
    ```python theme={null}
    print(f"Bulk modulus: {result['K']:.1f} GPa")
    print(f"Equilibrium volume: {result['v0']:.3f} Å³")
    print(f"Equilibrium energy: {result['e0']:.4f} eV")

    volumes  = result["eos"]["volumes"]
    energies = result["eos"]["energies"]
    ```
  </Step>
</Steps>

<Note>
  The EOS task uses a Birch-Murnaghan fit via `pymatgen.analysis.eos.BirchMurnaghan`. At least 4 converged points are needed for a meaningful fit. Increase `npoints` if you need higher resolution on the E-V curve.
</Note>
