Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of typed two-parted scheduler #592

Merged
merged 46 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
c093970
Implemented new Scheduler + test, started TimeAdvancer, adapted Compl…
sebastian-peter Aug 23, 2023
4ffeb93
Fixing tests
sebastian-peter Aug 24, 2023
840ad8b
Unused imports
sebastian-peter Sep 18, 2023
906cdff
Fix imports
sebastian-peter Oct 29, 2023
33846d9
Merge branch 'dev' into sp/#378-simscheduler-typed
sebastian-peter Oct 29, 2023
63e3935
Merge branch 'dev' into sp/#378-simscheduler-typed
sebastian-peter Nov 2, 2023
e2b6f5e
Introducing RuntimeNotifier
sebastian-peter Nov 2, 2023
98ae463
Implementing first test for TimeAdvancer, fixes
sebastian-peter Nov 3, 2023
9168b28
Merge branch 'dev' into sp/#378-simscheduler-typed
sebastian-peter Nov 7, 2023
d1c1e45
Removing unnecessary awaitedCompletions variable
sebastian-peter Nov 7, 2023
459c13f
spotless
sebastian-peter Nov 7, 2023
126a072
Some corrections
sebastian-peter Nov 7, 2023
5690822
Introducing ScheduleLock
sebastian-peter Nov 7, 2023
d8de5c7
Some fixes in Scheduler, TimeAdvancer and ScheduleLock
sebastian-peter Nov 8, 2023
69988aa
Fixing gradle spotless
sebastian-peter Nov 8, 2023
a89a445
Fixing PrimaryServiceProxy test
sebastian-peter Nov 8, 2023
b4383b6
Various fixes and enhancements for TimeAdvancer, adding tests and Sca…
sebastian-peter Nov 10, 2023
8f81384
Merge branch 'dev' into sp/#378-simscheduler-typed
sebastian-peter Nov 10, 2023
cc51e98
final case classes
sebastian-peter Nov 10, 2023
dc85e12
ScalaDoc updates for PriorityMultiBiSet
sebastian-peter Nov 10, 2023
83db14e
Adding missing test from old scheduler
sebastian-peter Nov 10, 2023
46798a8
Small improvement
sebastian-peter Nov 10, 2023
dfb086b
Fixes to scheduler, enhancing tests
sebastian-peter Nov 11, 2023
991646c
Removing unused object declaration
sebastian-peter Nov 11, 2023
86931f9
Adding FIXME
sebastian-peter Nov 11, 2023
6274669
Make check window optional in TimeAdvancer
sebastian-peter Nov 12, 2023
6a5fb27
Integrating new scheduler into SIMONA
sebastian-peter Nov 13, 2023
e98a193
Don't terminate TimeAdvancer if sim successful
sebastian-peter Nov 13, 2023
2c39177
Message to simulation root actor when sim ended
sebastian-peter Nov 13, 2023
2385ae8
Fixing warnings in TimeAdvancer
sebastian-peter Nov 13, 2023
0fa4499
Fixing RunSimonaStandaloneIT
sebastian-peter Nov 13, 2023
8fd8933
Fixing SimonaSimFailSpec
sebastian-peter Nov 13, 2023
5951181
Removing old scheduler
sebastian-peter Nov 13, 2023
5d9e911
Removing references to SimScheduler
sebastian-peter Nov 13, 2023
9a68b96
Removing unused data structures
sebastian-peter Nov 13, 2023
66d0cf2
Removing schedule lock from this PR again
sebastian-peter Nov 13, 2023
8385b34
Merge branch 'dev' into sp/#378-simscheduler-typed
danielfeismann Nov 17, 2023
b630f07
Updated ScalaDoc, as requested by @danielfeismann
sebastian-peter Nov 19, 2023
d9cd04b
Removing ScalaDoc from testing subclass
sebastian-peter Nov 19, 2023
2bf81e4
Adding to changelog
sebastian-peter Nov 19, 2023
1b207be
Adapting to adaptations in new simonaAPI
sebastian-peter Nov 20, 2023
64c3ac0
Adapting test to new simonaAPI
sebastian-peter Nov 20, 2023
e3dee63
Removing unused parameter
sebastian-peter Nov 20, 2023
26c4c38
Merge branch 'dev' into sp/#378-simscheduler-typed
sebastian-peter Nov 20, 2023
94f19be
Merge branch 'dev' into sp/#378-simscheduler-typed
sebastian-peter Nov 20, 2023
ace08e7
Merge branch 'dev' into sp/#378-simscheduler-typed
sebastian-peter Nov 21, 2023
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Changed from ComparableQuantity to squants in power flow [#554](https://github.com/ie3-institute/simona/issues/554)
- Reduce log level on missing diffuse irradiance [#629](https://github.com/ie3-institute/simona/issues/629)
- Updated to gradle 8.4 [#648](https://github.com/ie3-institute/simona/issues/648)
- Introducing new scheduling infrastructure:
- Two-parted scheduler in akka typed [#378](https://github.com/ie3-institute/simona/issues/378)
- Adapting to simonaAPI 0.3.0 (adapted message protocol)

## [3.0.0] - 2023-08-07

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ dependencies {
exclude group: 'edu.ie3'
}

implementation('com.github.ie3-institute:simonaAPI:0.2.0') {
implementation('com.github.ie3-institute:simonaAPI:0.3.0') {
exclude group: 'org.apache.logging.log4j'
exclude group: 'org.slf4j'
/* Exclude our own nested dependencies */
Expand Down
2 changes: 1 addition & 1 deletion docs/readthedocs/usersguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ In order to run an external simulation, several requirements have to be fulfille

- The external simulation should be implemented in its own project (repository).
- The project should include the *shadowJar* gradle plugin (``id "com.github.johnrengelman.shadow" version "x.y.z"``).
- A class (called *main class* here) needs to extend ``edu.ie3.simona.api.schedule.ExtSimulation`` and thus implement the two methods ``List<Long> initialize()`` and ``List<Long> doActivity(long tick)``. The method ``initialize`` is called when the external simulation needs to be initialized whereas the method ``doActivity`` is called when time step ``tick`` is triggered. ``initialize`` and ``doActivity`` must return a list of subsequent new ticks that the sub simulation should be scheduled at.
- A class (called *main class* here) needs to extend ``edu.ie3.simona.api.schedule.ExtSimulation`` and thus implement the two methods ``Optional<Long> initialize()`` and ``Optional<Long> doActivity(long tick)``. The method ``initialize`` is called when the external simulation needs to be initialized whereas the method ``doActivity`` is called when time step ``tick`` is triggered. ``initialize`` and ``doActivity`` can return a subsequent new tick that the sub simulation should be activated with next.
- For each data stream, a sub-interface of ``edu.ie3.simona.api.data.ExtDataSimulation`` needs to be implemented, such as ``edu.ie3.simona.api.data.ev.ExtEvSimulation``, and all methods of the interface have to be implemented. The *main class* could be the implementing class here.
- In order for SIMONA to use the external simulation, a class that extends ``edu.ie3.simona.api.ExtLinkInterface`` has to reside inside the project. The class has to implement the corresponding methods by returning the control stream and data stream implementations (could all be the same *main class*).
- When loading the external simulations, SIMONA is looking for the corresponding service files of the class ``edu.ie3.simona.api.ExtLinkInterface``. Therefor every external simulation needs the following service file: ``src/main/resources/META-INF/services/edu.ie3.simona.api.ExtLinkInterface``. The service file needs to contain the relative path to the class that extends ``edu.ie3.simona.api.ExtLinkInterface``.
Expand Down
20 changes: 20 additions & 0 deletions src/main/scala/edu/ie3/simona/actor/ActorUtil.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* © 2023. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/

package edu.ie3.simona.actor

import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}

object ActorUtil {
def stopOnError[M](
ctx: ActorContext[M],
msg: String
): Behavior[M] = {
ctx.log.error(s"$msg. Stopping.")
Behaviors.stopped
}
}
19 changes: 7 additions & 12 deletions src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport {
case Event(
TriggerWithIdMessage(
StartGridSimulationTrigger(currentTick),
triggerId,
_
triggerId
),
gridAgentBaseData: GridAgentBaseData
) =>
Expand Down Expand Up @@ -452,11 +451,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport {
environmentRefs.scheduler ! CompletionMessage(
simTriggerId,
Some(
Vector(
ScheduleTriggerMessage(
ActivityStartTrigger(currentTick + resolution),
self
)
ScheduleTriggerMessage(
ActivityStartTrigger(currentTick + resolution),
self
)
)
)
Expand Down Expand Up @@ -1011,8 +1008,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport {
/** Normally only reached by the superior (dummy) agent!
*
* Triggers a state transition to [[SimulateGrid]], informs the
* [[edu.ie3.simona.scheduler.SimScheduler]] about the finish of this sweep
* and requests a new trigger for itself for a new sweep (which means a new
* [[edu.ie3.simona.scheduler.Scheduler]] about the finish of this sweep and
* requests a new trigger for itself for a new sweep (which means a new
* [[StartGridSimulationTrigger]])
*
* @param gridAgentBaseData
Expand All @@ -1032,9 +1029,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport {
environmentRefs.scheduler ! CompletionMessage(
oldTrigger,
Some(
Vector(
ScheduleTriggerMessage(StartGridSimulationTrigger(currentTick), self)
)
ScheduleTriggerMessage(StartGridSimulationTrigger(currentTick), self)
)
)

Expand Down
25 changes: 12 additions & 13 deletions src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ import edu.ie3.util.TimeUtil
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit
import java.util.UUID
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.language.postfixOps

object GridAgent {
Expand Down Expand Up @@ -103,8 +101,7 @@ class GridAgent(
InitializeGridAgentTrigger(
gridAgentInitData: GridAgentInitData
),
triggerId,
_
triggerId
),
_
) =>
Expand Down Expand Up @@ -174,12 +171,14 @@ class GridAgent(

log.debug("Je suis initialized")

goto(Idle) using gridAgentBaseData replying CompletionMessage(
environmentRefs.scheduler ! CompletionMessage(
triggerId,
Some(
Vector(ScheduleTriggerMessage(ActivityStartTrigger(resolution), self))
ScheduleTriggerMessage(ActivityStartTrigger(resolution), self)
)
)

goto(Idle) using gridAgentBaseData
}

when(Idle) {
Expand All @@ -191,25 +190,25 @@ class GridAgent(
stay()

case Event(
TriggerWithIdMessage(ActivityStartTrigger(currentTick), triggerId, _),
TriggerWithIdMessage(ActivityStartTrigger(currentTick), triggerId),
gridAgentBaseData: GridAgentBaseData
) =>
log.debug("received activity start trigger {}", triggerId)

unstashAll()

goto(SimulateGrid) using gridAgentBaseData replying CompletionMessage(
environmentRefs.scheduler ! CompletionMessage(
triggerId,
Some(
Vector(
ScheduleTriggerMessage(
StartGridSimulationTrigger(currentTick),
self
)
ScheduleTriggerMessage(
StartGridSimulationTrigger(currentTick),
self
)
)
)

goto(SimulateGrid) using gridAgentBaseData

case Event(StopMessage(_), data: GridAgentBaseData) =>
// shutdown children
data.gridEnv.nodeToAssetAgents.foreach { case (_, actors) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ abstract class ParticipantAgent[
outputConfig
)
),
triggerId,
_
triggerId
),
_: ParticipantUninitializedStateData[PD]
) =>
Expand All @@ -136,7 +135,7 @@ abstract class ParticipantAgent[

when(Idle) {
case Event(
TriggerWithIdMessage(ActivityStartTrigger(currentTick), triggerId, _),
TriggerWithIdMessage(ActivityStartTrigger(currentTick), triggerId),
modelBaseStateData: ParticipantModelBaseStateData[PD, CD, M]
) if modelBaseStateData.services.isEmpty =>
/* An activity start trigger is sent and no data is awaited (neither secondary nor primary). Therefore go straight
Expand Down Expand Up @@ -166,7 +165,7 @@ abstract class ParticipantAgent[
)

case Event(
TriggerWithIdMessage(ActivityStartTrigger(currentTick), triggerId, _),
TriggerWithIdMessage(ActivityStartTrigger(currentTick), triggerId),
modelBaseStateData: ParticipantModelBaseStateData[PD, CD, M]
) =>
/* An activity start trigger is sent, but I'm not sure yet, if secondary data will arrive. Figure out, if someone
Expand All @@ -179,7 +178,7 @@ abstract class ParticipantAgent[
)

case Event(
TriggerWithIdMessage(ActivityStartTrigger(currentTick), triggerId, _),
TriggerWithIdMessage(ActivityStartTrigger(currentTick), triggerId),
fromOutsideBaseStateData: FromOutsideBaseStateData[M, PD]
) =>
/* An activity start trigger is sent, but I'm still expecting primary data. Go to HandleInformation and wait for
Expand Down Expand Up @@ -285,8 +284,7 @@ abstract class ParticipantAgent[
case Event(
TriggerWithIdMessage(
ActivityStartTrigger(activationTick),
triggerId,
_
triggerId
),
stateData: DataCollectionStateData[PD]
) =>
Expand Down Expand Up @@ -409,7 +407,7 @@ abstract class ParticipantAgent[
stay()

case Event(_: ProvisionMessage[_], _) |
Event(TriggerWithIdMessage(ActivityStartTrigger(_), _, _), _) =>
Event(TriggerWithIdMessage(ActivityStartTrigger(_), _), _) =>
/* I got faced to new data, also I'm not ready to handle it, yet OR I got asked to do something else, while I'm
* still busy, I will put it aside and answer it later */
stash()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,12 @@ protected trait ParticipantAgentFundamentals[

/* Confirm final initialization */
val (_, triggerId) = releaseTickAndTriggerId()
val newTriggerMessages =
ServiceActivationBaseStateData.tickToScheduleTriggerMessages(
val newTriggerMessage =
ServiceActivationBaseStateData.tickToScheduleTriggerMessage(
senderToMaybeTick._2,
self
)
scheduler ! CompletionMessage(triggerId, newTriggerMessages)
scheduler ! CompletionMessage(triggerId, newTriggerMessage)
goto(Idle) using stateData
}

Expand Down Expand Up @@ -710,11 +710,11 @@ protected trait ParticipantAgentFundamentals[
scheduler: ActorRef
): FSM.State[AgentState, ParticipantStateData[PD]] = {
/* Determine the very next tick, where activation is required */
val (maybeActivationTriggers, updatedBaseStateData) =
val (maybeActivationTrigger, updatedBaseStateData) =
popNextActivationTrigger(baseStateData)

val (_, triggerId) = releaseTickAndTriggerId()
scheduler ! CompletionMessage(triggerId, maybeActivationTriggers)
scheduler ! CompletionMessage(triggerId, maybeActivationTrigger)
unstashAll()
goto(Idle) using updatedBaseStateData
}
Expand All @@ -728,45 +728,43 @@ protected trait ParticipantAgentFundamentals[
* @param baseStateData
* Base state data to be updated
* @return
* An [[Option]] to a [[Seq]] of new [[ScheduleTriggerMessage]] s as well
* as the updated base state data. If the next activation tick is an
* additional activation, this tick is removed from the list of desired
* additional activations.
* An [[Option]] of new [[ScheduleTriggerMessage]] as well as the updated
* base state data. If the next activation tick is an additional
* activation, this tick is removed from the list of desired additional
* activations.
*/
def popNextActivationTrigger(
baseStateData: BaseStateData[PD]
): (Option[Seq[ScheduleTriggerMessage]], BaseStateData[PD]) = {
): (Option[ScheduleTriggerMessage], BaseStateData[PD]) = {
/* Determine what comes next: An additional activation or new data - or both at once */
val nextAdditionalActivation =
baseStateData.additionalActivationTicks.headOption
val nextDataTick =
baseStateData.foreseenDataTicks.values.toSeq.sorted.headOption.flatten

/* return a [[Option]] to a [[Seq]] of [[ScheduleTriggerMessage]]s */
def toMessageSeq: (Long, ActorRef) => Option[Seq[ScheduleTriggerMessage]] =
/* return a [[Option]] of [[ScheduleTriggerMessage]]s */
def toMessage: (Long, ActorRef) => Option[ScheduleTriggerMessage] =
(tick: Long, actorToBeTriggered: ActorRef) =>
Some(
Seq(
ScheduleTriggerMessage(
ActivityStartTrigger(tick),
actorToBeTriggered
)
ScheduleTriggerMessage(
ActivityStartTrigger(tick),
actorToBeTriggered
)
)

(nextAdditionalActivation, nextDataTick) match {
case (None, Some(dataTick)) =>
/* There is only a data tick available */
(
toMessageSeq(dataTick, self),
toMessage(dataTick, self),
baseStateData
)
case (Some(additionalTick), Some(dataTick))
if dataTick < additionalTick =>
/* The next foreseen activation will be based on foreseen data arrival. Do nothing else, then creating a
* trigger. */
(
toMessageSeq(dataTick, self),
toMessage(dataTick, self),
baseStateData
)
case (Some(additionalTick), _) =>
Expand All @@ -784,7 +782,7 @@ protected trait ParticipantAgentFundamentals[
)

(
toMessageSeq(additionalTick, self),
toMessage(additionalTick, self),
updatedBaseStateData
)
case (None, None) =>
Expand Down
12 changes: 5 additions & 7 deletions src/main/scala/edu/ie3/simona/api/ExtMessageUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,21 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{
}
import edu.ie3.simona.ontology.trigger.Trigger.ActivityStartTrigger

import scala.jdk.CollectionConverters.CollectionHasAsScala
import scala.jdk.OptionConverters.RichOptional

object ExtMessageUtils {
implicit class RichExtCompletion(
private val extCompl: ExtCompletionMessage
) {
def toSimona(triggerId: Long, triggerActor: ActorRef): CompletionMessage = {
val newTriggers =
Option.when(!extCompl.newTriggers.isEmpty) {
extCompl.newTriggers.asScala.map { tick =>
ScheduleTriggerMessage(ActivityStartTrigger(tick), triggerActor)
}.toSeq
val newTrigger =
extCompl.nextActivation.toScala.map { tick =>
ScheduleTriggerMessage(ActivityStartTrigger(tick), triggerActor)
}

CompletionMessage(
triggerId,
newTriggers
newTrigger
)
}
}
Expand Down
Loading