Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docs/api/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,42 @@ Concrete implementations of cell, converter, degradation, and thermal models.

::: simses.model.converter.fix_efficiency.FixedEfficiency

### Notton

::: simses.model.converter.notton.Notton

### AsymmetricNotton

::: simses.model.converter.notton.AsymmetricNotton

### NottonType1

::: simses.model.converter.notton.NottonType1

### NottonType2

::: simses.model.converter.notton.NottonType2

### NottonType3

::: simses.model.converter.notton.NottonType3

### Rampinelli

::: simses.model.converter.rampinelli.Rampinelli

### BonfiglioliTL4Q

::: simses.model.converter.bonfiglioli.BonfiglioliTL4Q

### BonfiglioliTL4QFieldData

::: simses.model.converter.bonfiglioli.BonfiglioliTL4QFieldData

### SungrowSC1000TL

::: simses.model.converter.sungrow.SungrowSC1000TL

### SinamicsS120

::: simses.model.converter.sinamics.SinamicsS120
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/cell-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ All values are per cell, taken directly from the model constructors.

## `SonyLFP`

A small-format cylindrical LFP cell (Sony/Murata US26650FTC1) with a flat OCV plateau, strong cycle life, and a notably asymmetric C-rate (1.0 charge, 6.6 discharge). OCV, hysteresis, and the entropic coefficient are 1-D lookups in SOC; internal resistance is a 2-D lookup over (SOC, T) with separate charge and discharge tables. This is the only cell in the library that ships a default degradation pair — [Naumann 2018 calendar](https://doi.org/10.1016/j.est.2018.01.019) and [Naumann 2020 cyclic](https://doi.org/10.1016/j.jpowsour.2019.227666) — so multi-year stationary-storage runs with aging work out of the box.
A small-format cylindrical LFP cell (Sony/Murata US26650FTC1) with a flat OCV plateau, strong cycle life, and a notably asymmetric C-rate (1.0 charge, 6.6 discharge). OCV, hysteresis, and the entropic coefficient are 1-D lookups in SOC; internal resistance is a 2-D lookup over (SOC, T) with separate charge and discharge tables. Ships a default degradation pair — [Naumann 2018 calendar](https://doi.org/10.1016/j.est.2018.01.019) and [Naumann 2020 cyclic](https://doi.org/10.1016/j.jpowsour.2019.227666) — so multi-year stationary-storage runs with aging work out of the box.

Additional source: Naumann, M. *Techno-economic evaluation of stationary lithium-ion energy storage systems with special consideration of aging*. PhD Thesis, Technical University Munich, 2018.

Expand Down Expand Up @@ -58,4 +58,4 @@ Writing a new cell model means subclassing `CellType` and implementing `open_cir

- [Battery concept](../concepts/battery.md) — how `CellType` composes into `Battery` and scales to pack level.
- [`CellType` API reference](../api/battery.md#cell-interface).
- [Models API reference](../api/models.md) — the `SonyLFP` and `Samsung94AhNMC` classes.
- [Models API reference](../api/models.md) — the shipped cell classes.
158 changes: 150 additions & 8 deletions docs/guides/converter-models.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
# Choosing a Converter Model

simses ships three built-in AC/DC converter loss models. All three implement the [`ConverterLossModel`][simses.converter.converter.ConverterLossModel] protocol and operate on normalised power (p.u. of the converter's rated `max_power`).
simses ships ten built-in AC/DC converter loss models, split into two categories. **Fit families** (`Notton`, `AsymmetricNotton`, `Rampinelli`) are generic parametric forms that require explicit coefficients; the `NottonTypeN` subclasses are presets of published coefficients. **Product models** (`BonfiglioliTL4Q`, `BonfiglioliTL4QFieldData`, `SungrowSC1000TL`, `SinamicsS120`, `SinamicsS120Fit`) are specific manufacturer hardware with baked-in coefficients. All implement the [`ConverterLossModel`][simses.converter.converter.ConverterLossModel] protocol and operate on normalised power (p.u. of the converter's rated `max_power`).

## Comparison

| Model | Loss shape | Data source | Direction symmetry | Constructor args |
|---|---|---|---|---|
| [`FixedEfficiency`](#fixedefficiency) | Constant η per direction | User-supplied | Symmetric by default; asymmetric via `(charge, discharge)` tuple | `eff: float \| tuple[float, float]` |
| [`SinamicsS120`](#sinamicss120) | 101-point lookup built from measured efficiency curves | Schimpe et al. 2018 | Symmetric by default; asymmetric via `use_discharging_curve=True` | `use_discharging_curve: bool = False` |
| [`SinamicsS120Fit`](#sinamicss120fit) | Closed-form fit `loss(p) = k₀(1 − e^(−m₀|p|)) + k₁|p| + k₂|p|²` | Least-squares fit to the same Schimpe 2018 data | Symmetric | (none) |
### Fit families (parametric, require coefficients)

At runtime all three evaluate to linear interpolation on a 101-point internal table — the distinction is how those points were generated.
| Model | Loss shape | Constructor args |
|---|---|---|
| [`Notton`](#notton) | `η(p) = p / (p + P0 + K·p²)`, symmetric | `P0: float, K: float` |
| [`AsymmetricNotton`](#asymmetricnotton) | Notton form with independent charge and discharge coefficients | `charge: (P0, K), discharge: (P0, K)` |
| [`Rampinelli`](#rampinelli) | `η(p) = p / (p + K0 + K1·p + K2·p²)`, symmetric | `K0: float, K1: float, K2: float` |
| [`NottonType1`](#nottontypen), [`NottonType2`](#nottontypen), [`NottonType3`](#nottontypen) | Three published inverter presets from Notton et al. 2010 | (none — no-arg subclasses of `Notton`) |

### Product models (specific hardware, no-arg constructors)

| Model | Inherits from | Data source | Direction symmetry |
|---|---|---|---|
| [`FixedEfficiency`](#fixedefficiency) | — | User-supplied | Symmetric by default; asymmetric via `(charge, discharge)` tuple |
| [`BonfiglioliTL4Q`](#bonfigliolitl4q) | `Notton` | F. Müller thesis — RPS TL-4Q datasheet | Symmetric |
| [`BonfiglioliTL4QFieldData`](#bonfigliolitl4qfielddata) | `AsymmetricNotton` | F. Müller thesis — FCR field data | Asymmetric |
| [`SungrowSC1000TL`](#sungrowsc1000tl) | `AsymmetricNotton` | F. Müller thesis — FCR field data | Asymmetric |
| [`SinamicsS120`](#sinamicss120) | — | Schimpe et al. 2018 (measured) | Symmetric by default; asymmetric via `use_discharging_curve=True` |
| [`SinamicsS120Fit`](#sinamicss120fit) | — | Schimpe et al. 2018 (parametric fit) | Symmetric |

At runtime all loss models except `FixedEfficiency` evaluate to linear interpolation on a 201-point internal table (101 per direction, mirrored about zero) — the distinction is how those points were generated.

## `FixedEfficiency`

Expand All @@ -27,6 +41,134 @@ converter = Converter(
)
```

## `Notton`

A generic parametric PV-inverter loss family with efficiency `η(p) = p / (p + P0 + K·p²)`, where `p` is the magnitude of normalised power. Symmetric about zero. Use this when you have a Notton-form fit to measured data, or when you want a physically reasonable two-parameter baseline.

For custom asymmetric ch/dch use [`AsymmetricNotton`](#asymmetricnotton). For the three published inverter presets see [`NottonTypeN`](#nottontypen) below.

Source: Notton, G., Lazarov, V., Stoyanov, L. *Optimal sizing of a grid-connected PV system for various PV module technologies and inclinations, inverter efficiency characteristics and locations*, [Renewable Energy 35(2) (2010) 541–554](https://doi.org/10.1016/j.renene.2009.07.013).

```python
from simses.converter import Converter
from simses.model.converter.notton import Notton

converter = Converter(
loss_model=Notton(P0=0.0072, K=0.0345),
max_power=100_000,
storage=battery,
)
```

## `AsymmetricNotton`

Notton-form fit with independent charge and discharge parameter sets. Each direction takes its own `(P0, K)` pair — useful for fitting converters whose measured efficiency curves differ between charging and discharging.

```python
from simses.converter import Converter
from simses.model.converter.notton import AsymmetricNotton

converter = Converter(
loss_model=AsymmetricNotton(
charge=(0.0072, 0.0345),
discharge=(0.005, 0.018),
),
max_power=100_000,
storage=battery,
)
```

## `NottonTypeN`

Three published inverter presets from Notton et al. 2010, provided as no-arg subclasses of `Notton` for convenience:

- `NottonType1` — `P0 = 0.0145, K = 0.0437`
- `NottonType2` — `P0 = 0.0072, K = 0.0345`
- `NottonType3` — `P0 = 0.0088, K = 0.1149`

```python
from simses.converter import Converter
from simses.model.converter.notton import NottonType2

converter = Converter(
loss_model=NottonType2(),
max_power=100_000,
storage=battery,
)
```

## `Rampinelli`

A three-parameter generalisation of the Notton form: `η(p) = p / (p + K0 + K1·p + K2·p²)`. The extra linear term lets the fit capture a wider range of measured efficiency curves — useful when a two-parameter Notton fit leaves a visible residual at mid-power.

Source: Rampinelli, G. A., Krenzinger, A., Chenlo Romero, F. *Mathematical models for efficiency of inverters used in grid connected photovoltaic systems*, [Renewable and Sustainable Energy Reviews 34 (2014) 578–587](https://doi.org/10.1016/j.rser.2014.03.047).

```python
from simses.converter import Converter
from simses.model.converter.rampinelli import Rampinelli

converter = Converter(
loss_model=Rampinelli(K0=0.003, K1=0.014, K2=0.003),
max_power=100_000,
storage=battery,
)
```

## `BonfiglioliTL4Q`

Bonfiglioli RPS TL-4Q inverter parameterised from the manufacturer datasheet — a `Notton` subclass with symmetric coefficients `P0 = 0.0072, K = 0.034`.

See [`BonfiglioliTL4QFieldData`](#bonfigliolitl4qfielddata) for the asymmetric variant parameterised from FCR field data.

Source: F. Müller (M.Sc. thesis, TUM) — Notton fit of the [Bonfiglioli RPS TL-4Q datasheet](http://www.docsbonfiglioli.com/pdf_documents/catalogue/VE_CAT_RTL-4Q_STD_ENG-ITA_R00_5_WEB.pdf).

```python
from simses.converter import Converter
from simses.model.converter.bonfiglioli import BonfiglioliTL4Q

converter = Converter(
loss_model=BonfiglioliTL4Q(),
max_power=100_000,
storage=battery,
)
```

## `BonfiglioliTL4QFieldData`

Bonfiglioli RPS TL-4Q inverter parameterised from frequency containment reserve (FCR) battery-system field measurements — an `AsymmetricNotton` subclass with distinct charge and discharge coefficients. Reflects real deployment losses including auxiliary consumption that the datasheet curves do not capture. Charge: `P0 = 0.00195, K = 0.01349`. Discharge: `P0 = 0.00292, K = 0.03609`.

Source: F. Müller (M.Sc. thesis, TUM) — field fit on FCR BESS deployments of the Bonfiglioli RPS TL-4Q.

```python
from simses.converter import Converter
from simses.model.converter.bonfiglioli import BonfiglioliTL4QFieldData

converter = Converter(
loss_model=BonfiglioliTL4QFieldData(),
max_power=100_000,
storage=battery,
)
```

## `SungrowSC1000TL`

Sungrow SC1000TL inverter, an `AsymmetricNotton` subclass backed by field data from an FCR battery system. Charge: `P0 = 0.007701864, K = 0.017290859`. Discharge: `P0 = 0.005511580, K = 0.018772838`.

The original thesis also characterised Rampinelli and rational-form fits of the same measurements; the Notton fit was the default in the legacy simses implementation and is the one ported here.

Source: F. Müller (M.Sc. thesis, TUM) — field fit on a Sungrow SC1000TL inverter.

```python
from simses.converter import Converter
from simses.model.converter.sungrow import SungrowSC1000TL

converter = Converter(
loss_model=SungrowSC1000TL(),
max_power=1_000_000, # 1 MW rated
storage=battery,
)
```

## `SinamicsS120`

Lookup-table model built from measured efficiency curves for the Siemens Sinamics S120, a common utility-scale drive. The bundled CSV carries 1001 sample points, re-sampled down to 101 at construction. The measurement splits into `Charging` and `Discharging` columns that differ by a mean of 0.23 % and a maximum of 0.40 %. By default the charging curve is mirrored onto the discharge branch so the model is symmetric about zero; set `use_discharging_curve=True` to preserve the measured asymmetry.
Expand Down Expand Up @@ -69,4 +211,4 @@ Writing a new converter loss model means implementing `ac_to_dc(power_norm)` and

- [Converter concept](../concepts/converter.md) — how `ConverterLossModel` composes into `Converter`, the two-pass resolution, and sign handling at the AC/DC boundary.
- [`Converter` API reference](../api/converter.md).
- [Models API reference](../api/models.md) — the three shipped loss models.
- [Models API reference](../api/models.md) — all ten shipped loss models.
2 changes: 1 addition & 1 deletion docs/guides/extending-cells.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
How to implement a new cell chemistry as a `CellType` subclass, drop it into a `Battery`, and plug it into the existing test harness.

!!! info "Who this is for"
Researchers or engineers who want to simulate a cell not covered by the shipped `SonyLFP` / `Samsung94AhNMC`. If you just need to pick between the existing models, see [Choosing a Cell Model](cell-models.md) instead. For the architectural picture of how `CellType` and `Battery` interact, see [Battery concept](../concepts/battery.md#battery-and-celltype).
Researchers or engineers who want to simulate a cell not covered by the shipped models (`SonyLFP`, `Samsung94AhNMC`). If you just need to pick between the existing models, see [Choosing a Cell Model](cell-models.md) instead. For the architectural picture of how `CellType` and `Battery` interact, see [Battery concept](../concepts/battery.md#battery-and-celltype).

## The contract

Expand Down
40 changes: 40 additions & 0 deletions src/simses/model/converter/bonfiglioli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from simses.model.converter.notton import AsymmetricNotton, Notton


class BonfiglioliTL4Q(Notton):
"""Bonfiglioli RPS TL-4Q converter — datasheet parameterisation.

Symmetric Notton-form fit with ``P0 = 0.0072, K = 0.034`` measured
under manufacturer datasheet conditions.

See :class:`BonfiglioliTL4QFieldData` for the asymmetric variant
parameterised from FCR field data.

Source: F. Müller (M.Sc. thesis, TUM) — Notton fit of the
`Bonfiglioli RPS TL-4Q datasheet
<http://www.docsbonfiglioli.com/pdf_documents/catalogue/VE_CAT_RTL-4Q_STD_ENG-ITA_R00_5_WEB.pdf>`_.
"""

def __init__(self) -> None:
super().__init__(P0=0.0072, K=0.034)


class BonfiglioliTL4QFieldData(AsymmetricNotton):
"""Bonfiglioli RPS TL-4Q converter — FCR field-data parameterisation.

Asymmetric Notton-form fit measured on frequency containment reserve
(FCR) battery systems; reflects real deployment losses including
auxiliary consumption. Charge: ``P0 = 0.00195, K = 0.01349``.
Discharge: ``P0 = 0.00292, K = 0.03609``.

See :class:`BonfiglioliTL4Q` for the symmetric datasheet variant.

Source: F. Müller (M.Sc. thesis, TUM) — field fit on FCR BESS
deployments of the Bonfiglioli RPS TL-4Q.
"""

def __init__(self) -> None:
super().__init__(
charge=(0.00195, 0.01349),
discharge=(0.00292, 0.03609),
)
Loading
Loading