Skip to content

Commit

Permalink
Adapting load models. Removing now unused classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
staudtMarius committed Sep 20, 2024
1 parent f86af7c commit 1ad02be
Show file tree
Hide file tree
Showing 25 changed files with 294 additions and 1,355 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,9 @@ import edu.ie3.simona.agent.participant.statedata.ParticipantStateData.Participa
import edu.ie3.simona.config.SimonaConfig.LoadRuntimeConfig
import edu.ie3.simona.model.participant.CalcRelevantData.LoadRelevantData
import edu.ie3.simona.model.participant.ModelState.ConstantState
import edu.ie3.simona.model.participant.load.profile.ProfileLoadModel
import edu.ie3.simona.model.participant.load.profile.ProfileLoadModel.ProfileRelevantData
import edu.ie3.simona.model.participant.load.random.RandomLoadModel
import edu.ie3.simona.model.participant.load.random.RandomLoadModel.RandomRelevantData
import edu.ie3.simona.model.participant.load.{
FixedLoadModel,
LoadModel,
LoadModelBehaviour,
}
import edu.ie3.simona.model.participant.load.ProfileLoadModel.ProfileRelevantData
import edu.ie3.simona.model.participant.load.RandomLoadModel.RandomRelevantData
import edu.ie3.simona.model.participant.load._
import org.apache.pekko.actor.{ActorRef, Props}

object LoadAgent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,15 @@ import edu.ie3.simona.model.SystemComponent
import edu.ie3.simona.model.participant.CalcRelevantData.LoadRelevantData
import edu.ie3.simona.model.participant.ModelState.ConstantState
import edu.ie3.simona.model.participant.load.FixedLoadModel.FixedLoadRelevantData
import edu.ie3.simona.model.participant.load.profile.ProfileLoadModel
import edu.ie3.simona.model.participant.load.profile.ProfileLoadModel.ProfileRelevantData
import edu.ie3.simona.model.participant.load.random.RandomLoadModel
import edu.ie3.simona.model.participant.load.random.RandomLoadModel.RandomRelevantData
import edu.ie3.simona.model.participant.load.{
FixedLoadModel,
LoadModel,
LoadReference,
}
import edu.ie3.simona.model.participant.load.ProfileLoadModel.ProfileRelevantData
import edu.ie3.simona.model.participant.load.RandomLoadModel.RandomRelevantData
import edu.ie3.simona.model.participant.load._
import edu.ie3.simona.model.participant.{FlexChangeIndicator, ModelState}
import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage.{
FlexRequest,
FlexResponse,
}
import edu.ie3.simona.ontology.messages.services.LoadProfileMessage.LoadProfileData
import edu.ie3.simona.util.SimonaConstants
import edu.ie3.simona.util.TickUtil._
import edu.ie3.util.quantities.PowerSystemUnits.PU
Expand Down Expand Up @@ -190,6 +185,46 @@ protected trait LoadAgentFundamentals[LD <: LoadRelevantData, LM <: LoadModel[
)
}

/** @param baseStateData
* base state data
* @param currentTick
* current tick
* @return
* the [[LoadProfileData]]
*/
protected def retrieveLoadProfileData(
baseStateData: ParticipantModelBaseStateData[
ApparentPower,
_ <: LoadRelevantData,
ConstantState.type,
LM,
],
currentTick: Long,
): LoadProfileData = {
// take the last load profile data, not necessarily the one for the current tick:
// we might receive flex control messages for irregular ticks
val (_, secondaryData) = baseStateData.receivedSecondaryDataStore
.last(currentTick)
.getOrElse(
throw new InconsistentStateException(
s"The model ${baseStateData.model} was not provided with any secondary data so far."
)
)

/* extract load profile data from secondary data, which should have been requested and received before */
secondaryData
.collectFirst {
// filter secondary data for weather data
case (_, data: LoadProfileData) =>
data
}
.getOrElse(
throw new InconsistentStateException(
s"The model ${baseStateData.model} was not provided with needed weather data."
)
)
}

override def buildModel(
inputModel: InputModelContainer[LoadInput],
modelConfig: LoadRuntimeConfig,
Expand Down Expand Up @@ -287,7 +322,7 @@ protected trait LoadAgentFundamentals[LD <: LoadRelevantData, LM <: LoadModel[
*
* @param baseStateData
* The base state data with collected secondary data
* @param maybeLastModelState
* @param lastModelState
* Optional last model state
* @param currentTick
* Tick, the trigger belongs to
Expand All @@ -306,11 +341,31 @@ protected trait LoadAgentFundamentals[LD <: LoadRelevantData, LM <: LoadModel[
lastModelState: ConstantState.type,
currentTick: Long,
scheduler: ActorRef,
): FSM.State[AgentState, ParticipantStateData[ApparentPower]] =
throw new InconsistentStateException(
s"Load model is not able to calculate power with secondary data."
): FSM.State[AgentState, ParticipantStateData[ApparentPower]] = {
val voltage =
getAndCheckNodalVoltage(baseStateData, currentTick)

val relevantData =
createCalcRelevantData(
baseStateData,
currentTick,
)

val result = baseStateData.model.calculatePower(
currentTick,
voltage,
ConstantState,
relevantData,
)

updateValueStoresInformListenersAndGoToIdleWithUpdatedBaseStateData(
scheduler,
baseStateData,
AccompaniedSimulationResult(result),
relevantData,
)
}

/** Determine the average result within the given tick window
*
* @param tickToResults
Expand Down Expand Up @@ -465,10 +520,14 @@ object LoadAgentFundamentals {
ProfileLoadModel,
],
currentTick: Long,
): ProfileRelevantData =
): ProfileRelevantData = {
val data = retrieveLoadProfileData(baseStateData, currentTick)

ProfileRelevantData(
currentTick.toDateTime(baseStateData.startDate)
data.averagePower,
data.maxPower,
)
}

/** Partial function, that is able to transfer
* [[ParticipantModelBaseStateData]] (holding the actual calculation model)
Expand Down Expand Up @@ -525,10 +584,9 @@ object LoadAgentFundamentals {
RandomLoadModel,
],
tick: Long,
): RandomRelevantData =
RandomRelevantData(
tick.toDateTime(baseStateData.startDate)
)
): RandomRelevantData = RandomRelevantData(
retrieveLoadProfileData(baseStateData, currentTick).averagePower
)

/** Partial function, that is able to transfer
* [[ParticipantModelBaseStateData]] (holding the actual calculation model)
Expand Down
46 changes: 0 additions & 46 deletions src/main/scala/edu/ie3/simona/model/participant/load/DayType.scala

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
* Research group Distribution grid planning and operation
*/

package edu.ie3.simona.model.participant.load.profile
package edu.ie3.simona.model.participant.load

import edu.ie3.datamodel.exceptions.SourceException
import edu.ie3.datamodel.models.input.system.LoadInput
import edu.ie3.datamodel.models.profile.StandardLoadProfile
import edu.ie3.simona.model.participant.CalcRelevantData.LoadRelevantData
import edu.ie3.simona.model.participant.ModelState.ConstantState
import edu.ie3.simona.model.participant.control.QControl
import edu.ie3.simona.model.participant.load.LoadReference._
import edu.ie3.simona.model.participant.load.profile.ProfileLoadModel.ProfileRelevantData
import edu.ie3.simona.model.participant.load.{LoadModel, LoadReference}
import edu.ie3.simona.model.participant.load.ProfileLoadModel.ProfileRelevantData
import edu.ie3.simona.service.load.LoadProfileStore
import edu.ie3.util.scala.OperationInterval
import squants.Power

import java.time.ZonedDateTime
import java.util.UUID

/** Power model consuming power according to standard load profiles
Expand Down Expand Up @@ -57,11 +57,6 @@ final case class ProfileLoadModel(
cosPhiRated,
) {

private val loadProfileStore: LoadProfileStore = LoadProfileStore()

/* maximum energy throughout the year of the selected load profile*/
private val profileMaxPower = loadProfileStore.maxPower(loadProfile)

/* energy reference is always models yearly energy consumption divided by the energy the profile is scaled to */
private lazy val energyReferenceScalingFactor =
reference match {
Expand All @@ -84,26 +79,25 @@ final case class ProfileLoadModel(
modelState: ConstantState.type,
data: ProfileRelevantData,
): Power = {
/* The power comes in W and is delivered all 15 minutes */
val averagePower: Power = loadProfileStore
.entry(data.date, loadProfile)

/* The power comes in kW and is delivered all 15 minutes */
reference match {
case ActivePower(activePower) =>
/* scale the reference active power based on the profiles averagePower/maxPower ratio */
val referenceScalingFactor = averagePower / profileMaxPower
val referenceScalingFactor = data.averagePower / data.maxPower
activePower * referenceScalingFactor
case _: EnergyConsumption =>
/* scale the profiles average power based on the energyConsumption/profileEnergyScaling(=1000kWh/year) ratio */
averagePower * energyReferenceScalingFactor
data.averagePower * energyReferenceScalingFactor
}
}
}

object ProfileLoadModel {

final case class ProfileRelevantData(date: ZonedDateTime)
extends LoadRelevantData
final case class ProfileRelevantData(
averagePower: Power,
maxPower: Power,
) extends LoadRelevantData

def apply(
input: LoadInput,
Expand All @@ -120,15 +114,23 @@ object ProfileLoadModel {
LoadModel.scaleSRatedActivePower(scaledInput, power)

case LoadReference.EnergyConsumption(energyConsumption) =>
val loadProfileMax =
LoadProfileStore().maxPower(
val loadProfileMax = LoadProfileStore
.maxPower(
scaledInput.getLoadProfile.asInstanceOf[StandardLoadProfile]
)
.getOrElse(
throw new SourceException(
s"Expected a maximal power value for this load profile: ${input.getLoadProfile}!"
)
)

LoadModel.scaleSRatedEnergy(
scaledInput,
energyConsumption,
loadProfileMax,
LoadProfileStore.defaultLoadProfileEnergyScaling,
LoadProfileStore.profileScaling(
scaledInput.getLoadProfile.asInstanceOf[StandardLoadProfile]
),
)
}

Expand Down
Loading

0 comments on commit 1ad02be

Please sign in to comment.