Skip to content

Commit

Permalink
Merge branch 'dev' into df/#1176-heat-pump-targetTemp
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGELOG.md
  • Loading branch information
danielfeismann committed Feb 17, 2025
2 parents b4c2389 + 4ea6c77 commit 30669ea
Show file tree
Hide file tree
Showing 31 changed files with 976 additions and 330 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Checking the number of slack nodes [#1122](https://github.com/ie3-institute/simona/issues/1122)
- Enhance exception message in case of InvalidGridException [#1124](https://github.com/ie3-institute/simona/issues/1124)
- Integration test for thermal grids [#1145](https://github.com/ie3-institute/simona/issues/1145)
- Added `VoltageLimits` [#1133](https://github.com/ie3-institute/simona/issues/1133)
- Change thermal house behaviour to heat till targetTemperature [#1176](https://github.com/ie3-institute/simona/issues/1176)

### Changed
Expand Down Expand Up @@ -129,6 +130,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Enhance EmAggregate of SelfOpt to cope with other targetLimits [#1131](https://github.com/ie3-institute/simona/issues/1131)
- Switched to `pureconfig` [#608](https://github.com/ie3-institute/simona/issues/608)
- Removing generated methods and cleaning up in config [#1170](https://github.com/ie3-institute/simona/issues/1170)
- Changed `pvInput` values in `PvInputTestData` to more realistic values [#1144](https://github.com/ie3-institute/simona/issues/1144)

### Fixed
- Fix rendering of references in documentation [#505](https://github.com/ie3-institute/simona/issues/505)
Expand Down Expand Up @@ -176,7 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Rename `PrimaryDataWithApparentPower` to `PrimaryDataWithComplexPower` [#1140](https://github.com/ie3-institute/simona/issues/1140)
- Refactoring of `ThermalGrid.handleInfeed` to fix thermal storage recharge correctly when empty [#930](https://github.com/ie3-institute/simona/issues/930)
- Move `ScheduleServiceActivation` out of `RegistrationResponseMessage` [#1143](https://github.com/ie3-institute/simona/issues/1143)
- Handle edge cases of thermal grid [#1167](https://github.com/ie3-institute/simona/issues/1167)
- Check for runningHp when handling infeed to thermalGrid [#1167](https://github.com/ie3-institute/simona/issues/1167)

## [3.0.0] - 2023-08-07

Expand Down
17 changes: 16 additions & 1 deletion docs/readthedocs/_static/bibliography/bibtexAll.bib
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,19 @@ @MISC{Radiation_ECMWF
author = {Robin Hogan},
title = {Radiation Quantities in the ECMWF model and MARS},
howpublished = {\url{https://www.ecmwf.int/sites/default/files/elibrary/2015/18490-radiation-quantities-ecmwf-model-and-mars.pdf}}
}
}

@misc{EN_50160,
title = {EN 50160:2020-11, Voltage characteristics of electricity supplied by public electricity networks},
publisher = {CENELEC},
type = {NORM},
year = {2022},
date = {2022-12-01},
}

@online{EU_2017/1485,
author = {{The European Commission}},
title = {COMMISSION REGULATION (EU) 2017/1485 of 2 August 2017 establishing a guideline on electricity transmission system operation},
date = {2017-08-02},
url = {https://eur-lex.europa.eu/legal-content/DE/TXT/?uri=CELEX%3A32017R1485},
}
27 changes: 27 additions & 0 deletions docs/readthedocs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ Tba:

## Grid configuration

### Reference System
The reference system contains a list of voltage levels. Each element includes the nominal apparent power, the nominal
voltage and the separate configuration of each voltage level. The voltage level configuration is composed of the identifier
and the nominal voltage.
Expand All @@ -268,6 +269,32 @@ simona.gridConfig.refSystems = [
Further typical voltage levels which can be used in the simulation and the configuration of individual reference systems
are described in the documentation of [reference system](models/reference_system).

### Voltage limits

The voltage limits contains a list of voltage levels. Each element includes the minimal and maximal allowed voltage and
the separate configuration of each voltage level. The voltage level configuration is composed of the identifier and the
nominal voltage.

The configuration of a voltage limits is optional. If no configuration is provided by the user, the default
[voltage limits](models/voltage_limits) that includes all common german voltage levels is used. For those users
who need other voltage levels than the common german voltage levels or different voltage limits, they can configure
their limits as shown below.

The voltage limits can be configured as follows:

```
simona.gridConfig.voltageLimits = [
{vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Lv", vNom = "0.4 kV"}]},
{vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Mv", vNom = "20 kV"}]},
{vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Hv", vNom = "110 kV"}]},
{vMin = 0.9, vMax = 1.05, voltLvls = [{id = "EHV", vNom = "380 kV"}]},
]
```

Further typical voltage levels which can be used in the simulation and the configuration of individual voltage limits
are described in the documentation of [voltage limits](models/voltage_limits).


## Power flow configuration

Maximum allowed deviation in power between two sweeps, before overall convergence is assumed:
Expand Down
1 change: 1 addition & 0 deletions docs/readthedocs/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ models/three_winding_transformer_model
models/reference_system
models/thermal_grid_model
models/thermal_house_model
models/voltage_limits
```

## System Participant Related Models
Expand Down
65 changes: 65 additions & 0 deletions docs/readthedocs/models/voltage_limits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
(voltage_limits)=

# Voltage Limits

The voltage limits are built up by specifying the included voltage levels. The following table describes typical network
levels and their parameterization. They are primarily used for the optional congestion management.

## Default voltage limits

```{list-table}
:widths: auto
:header-rows: 1
* - Voltage level (id)
- Minimal voltage (vMin)
- Maximal voltage (vMax)
* - LV
- 0.9 p.u.
- 1.1 p.u.
* - MV (10 kV)
- 0.9 p.u.
- 1.1 p.u.
* - MV (20 kV)
- 0.9 p.u.
- 1.1 p.u.
* - MV (30 kV)
- 0.9 p.u.
- 1.1 p.u.
* - HV
- 0.9 p.u.
- 1.1 p.u.
* - EHV (220 kV)
- 0.9 p.u.
- 1.118 p.u.
* - EHV (380 kV)
- 0.9 p.u.
- 1.05 p.u.
```

**References:**

* {cite:cts}`EN_50160`
* {cite:cts}`EU_2017/1485`

## Configuration of the voltage limits

To configure the voltage limits, the voltage levels listed in the table above must be selected and integrated into the
config. The individual voltage level configuration (voltLvls) according to the example below. Each voltage level consists
of an identifier and the nominal voltage.

```
simona.gridConfig.voltageLimits = [
{vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Lv", vNom = "0.4 kV"}]},
{vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Mv", vNom = "20 kV"}]},
{vMin = 0.9, vMax = 1.1, voltLvls = [{id = "Hv", vNom = "110 kV"}]},
{vMin = 0.9, vMax = 1.05, voltLvls = [{id = "EHV", vNom = "380 kV"}]},
]
```
13 changes: 13 additions & 0 deletions src/main/resources/config/config-template.conf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ RefSystemConfig {
gridIds: [string] # Sub grid numbers to apply to, expl.: 1,2,4..10
}

#@define
VoltageLimitsConfig {
vMin: double # minimal voltage
vMax: double # maximal voltage
#@optional
voltLvls: [VoltLvlConfig] # Voltage levels to apply to
#@optional
gridIds: [string] # Sub grid numbers to apply to, expl.: 1,2,4..10
}

#@define abstract extends !java.io.Serializable
BaseRuntimeConfig {
uuids: [string] # Unique id to identify the system participant models this config applies for
Expand Down Expand Up @@ -363,6 +373,9 @@ simona.powerflow.stopOnFailure = boolean | false
#@optional
simona.gridConfig.refSystems = [RefSystemConfig]

#@optional
simona.gridConfig.voltageLimits = [VoltageLimitsConfig]

##################################################################
# Event Configuration
##################################################################
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ object GridAgent extends DBFSAlgorithm {
val gridModel = GridModel(
subGridContainer,
refSystem,
gridAgentInitData.voltageLimits,
TimeUtil.withDefaults.toZonedDateTime(
constantData.simonaConfig.simona.time.startDateTime
),
Expand Down
7 changes: 6 additions & 1 deletion src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import edu.ie3.simona.agent.grid.ReceivedValuesStore.NodeToReceivedPower
import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage
import edu.ie3.simona.config.SimonaConfig
import edu.ie3.simona.event.ResultEvent
import edu.ie3.simona.model.grid.{GridModel, RefSystem}
import edu.ie3.simona.model.grid.{GridModel, RefSystem, VoltageLimits}
import edu.ie3.simona.ontology.messages.Activation
import org.apache.pekko.actor.typed.ActorRef

Expand Down Expand Up @@ -69,12 +69,17 @@ object GridAgentData {
* @param subGridGateToActorRef
* information on inferior and superior grid connections [[SubGridGate]] s
* and [[ActorRef]] s of the corresponding [[GridAgent]]s
* @param refSystem
* of the grid
* @param voltageLimits
* of the grid, used to evaluate voltage congestion
*/
final case class GridAgentInitData(
subGridContainer: SubGridContainer,
thermalIslandGrids: Seq[ThermalGrid],
subGridGateToActorRef: Map[SubGridGate, ActorRef[GridAgent.Request]],
refSystem: RefSystem,
voltageLimits: VoltageLimits,
) extends GridAgentData
with GridAgentDataHelper {
override protected val subgridGates: Vector[SubGridGate] =
Expand Down
142 changes: 87 additions & 55 deletions src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,10 @@ object ConfigFailFast extends LazyLogging {
checkTimeConfig(simonaConfig.simona.time)

// check if the provided combinations of refSystems provided are valid
val refSystems = simonaConfig.simona.gridConfig.refSystems
if (refSystems.isDefined)
refSystems.foreach(refsys => checkRefSystem(refsys))
simonaConfig.simona.gridConfig.refSystems.foreach(checkRefSystem)

// check if the provided combinations of voltageLimits provided are valid
simonaConfig.simona.gridConfig.voltageLimits.foreach(checkVoltageLimits)

/* Check all participant model configurations */
checkParticipantRuntimeConfiguration(
Expand Down Expand Up @@ -454,72 +455,103 @@ object ConfigFailFast extends LazyLogging {
* @param refSystems
* a list of [[SimonaConfig.RefSystemConfig]]s that should be checked
*/

private def checkRefSystem(refSystems: List[RefSystemConfig]): Unit = {
private def checkRefSystem(
refSystems: List[RefSystemConfig]
): Unit = {
refSystems.foreach { refSystem =>
{
val voltLvls =
refSystem.voltLvls.getOrElse(List.empty[SimonaConfig.VoltLvlConfig])
val gridIds = refSystem.gridIds.getOrElse(List.empty[String])
checkGridConfig(refSystem, "refSystem")

if (voltLvls.isEmpty && gridIds.isEmpty)
refSystem.sNom match {
case ConfigConventions.refSystemQuantRegex(_) =>
case _ =>
throw new InvalidConfigParameterException(
"The provided values for voltLvls and gridIds are empty! " +
s"At least one of these optional parameters has to be provided for a valid refSystem! " +
s"Provided refSystem is: $refSystem."
s"Invalid value for sNom from provided refSystem $refSystem. Is a valid unit provided?"
)
}

voltLvls.foreach { voltLvl =>
Try(Quantities.getQuantity(voltLvl.vNom)) match {
case Success(quantity) =>
if (!quantity.getUnit.isCompatible(Units.VOLT))
throw new InvalidConfigParameterException(
s"The given nominal voltage '${voltLvl.vNom}' cannot be parsed to electrical potential! Please provide the volt level with its unit, e.g. \"20 kV\""
)
case Failure(exception) =>
throw new InvalidConfigParameterException(
s"The given nominal voltage '${voltLvl.vNom}' cannot be parsed to a quantity. Did you provide the volt level with it's unit (e.g. \"20 kV\")?",
exception,
)
}
}
refSystem.vNom match {
case ConfigConventions.refSystemQuantRegex(_) =>
case _ =>
throw new InvalidConfigParameterException(
s"Invalid value for vNom from provided refSystem $refSystem. Is a valid unit provided?"
)
}
}
}

gridIds.foreach {
case gridIdRange @ ConfigConventions.gridIdDotRange(from, to) =>
rangeCheck(from.toInt, to.toInt, gridIdRange)
case gridIdRange @ ConfigConventions.gridIdMinusRange(from, to) =>
rangeCheck(from.toInt, to.toInt, gridIdRange)
case ConfigConventions.singleGridId(_) =>
case gridId =>
throw new InvalidConfigParameterException(
s"The provided gridId $gridId is malformed!"
)
}
/** Sanity checks for a [[SimonaConfig.VoltageLimitsConfig]]
*
* @param voltageLimits
* the [[SimonaConfig.VoltageLimitsConfig]] that should be checked
*/
private def checkVoltageLimits(
voltageLimits: List[VoltageLimitsConfig]
): Unit = {
voltageLimits.foreach { limit =>
checkGridConfig(limit, "voltage limit")

refSystem.sNom match {
case ConfigConventions.refSystemQuantRegex(_) =>
case _ =>
throw new InvalidConfigParameterException(
s"Invalid value for sNom from provided refSystem $refSystem. Is a valid unit provided?"
)
}
if (limit.vMin >= limit.vMax) {
throw new InvalidConfigParameterException(
s"Invalid value for vMin and vMax from provided voltage limit $limit. Is vMin smaller than vMax?"
)
}
}
}

/** Method to check the common elements of a
* [[SimonaConfig.Simona.GridConfig]].
* @param gridConfig
* the individual config
* @param configType
* the type of config (e.g. refSystem)
*/
private def checkGridConfig(
gridConfig: GridConfigParams,
configType: String,
): Unit = {
val voltLvls = gridConfig.voltLvls.getOrElse(List.empty)
val gridIds = gridConfig.gridIds.getOrElse(List.empty)

if (voltLvls.isEmpty && gridIds.isEmpty)
throw new InvalidConfigParameterException(
"The provided values for voltLvls and gridIds are empty! " +
s"At least one of these optional parameters has to be provided for a valid $configType! " +
s"Provided $configType is: $gridConfig."
)

refSystem.vNom match {
case ConfigConventions.refSystemQuantRegex(_) =>
case _ =>
voltLvls.foreach { voltLvl =>
Try(Quantities.getQuantity(voltLvl.vNom)) match {
case Success(quantity) =>
if (!quantity.getUnit.isCompatible(Units.VOLT))
throw new InvalidConfigParameterException(
s"Invalid value for vNom from provided refSystem $refSystem. Is a valid unit provided?"
s"The given nominal voltage '${voltLvl.vNom}' cannot be parsed to electrical potential! Please provide the volt level with its unit, e.g. \"20 kV\""
)
}
}

def rangeCheck(from: Int, to: Int, gridIdRange: String): Unit = {
if (from >= to)
case Failure(exception) =>
throw new InvalidConfigParameterException(
s"Invalid gridId Range $gridIdRange. Start $from cannot be equals or bigger than end $to."
s"The given nominal voltage '${voltLvl.vNom}' cannot be parsed to a quantity. Did you provide the volt level with it's unit (e.g. \"20 kV\")?",
exception,
)
}
}

gridIds.foreach {
case gridIdRange @ ConfigConventions.gridIdDotRange(from, to) =>
rangeCheck(from.toInt, to.toInt, gridIdRange)
case gridIdRange @ ConfigConventions.gridIdMinusRange(from, to) =>
rangeCheck(from.toInt, to.toInt, gridIdRange)
case ConfigConventions.singleGridId(_) =>
case gridId =>
throw new InvalidConfigParameterException(
s"The provided gridId $gridId is malformed!"
)
}

def rangeCheck(from: Int, to: Int, gridIdRange: String): Unit = {
if (from >= to)
throw new InvalidConfigParameterException(
s"Invalid gridId Range $gridIdRange. Start $from cannot be equals or bigger than end $to."
)
}
}

private def checkGridDataSource(
Expand Down
Loading

0 comments on commit 30669ea

Please sign in to comment.