Skip to content

Enhancing and refactoring ExtCoSimulation. #238

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

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added Bao and Staudt to the list of reviewers [#216](https://github.com/ie3-institute/simonaAPI/issues/216)
- Documentation for this API [#230](https://github.com/ie3-institute/simonaAPI/issues/230)


### Changed
- Refactoring `ExtCoSimulation` [#237](https://github.com/ie3-institute/simonaAPI/issues/237)

## [0.6.0] - 2024-12-02

### Added
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* © 2025. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/

package edu.ie3.simona.api.data;

import edu.ie3.datamodel.models.value.Value;
import edu.ie3.simona.api.data.ontology.DataMessageFromExt;
import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage;
import java.util.*;
import org.apache.pekko.actor.ActorRef;
import org.slf4j.Logger;

public abstract class ExtInputDataConnectionWithMapping<
M extends DataMessageFromExt, V extends Value>
implements ExtInputDataConnection {

/** Actor reference to service that handles data within SIMONA */
private ActorRef dataService;

/** Actor reference to adapter that handles scheduler control flow in SIMONA */
private ActorRef extSimAdapter;

/** Assets that provide data to SIMONA */
private final Map<String, UUID> extDataMapping;

protected ExtInputDataConnectionWithMapping(Map<String, UUID> extDataMapping) {
this.extDataMapping = extDataMapping;
}

@Override
public void setActorRefs(ActorRef dataService, ActorRef extSimAdapter) {
this.dataService = dataService;
this.extSimAdapter = extSimAdapter;
}

/**
* Converts the data and sends them to SIMONA.
*
* @param tick current tick
* @param data to be converted and send
* @param maybeNextTick option for the next tick in the simulation
* @param log logger
*/
public abstract void convertAndSend(
long tick, Map<String, Value> data, Optional<Long> maybeNextTick, Logger log);

/** Provide data from an external simulation for one tick. */
public abstract void provideData(long tick, Map<UUID, V> data, Optional<Long> maybeNextTick);

/**
* Send information from the external simulation to SIMONA's external primary data service.
* Furthermore, ExtSimAdapter within SIMONA is instructed to activate the ev data service with the
* current tick.
*
* @param msg the data/information that is sent to SIMONA's external primary data service
*/
public void sendExtMsg(M msg) {
dataService.tell(msg, ActorRef.noSender());
// we need to schedule data receiver activation with scheduler
extSimAdapter.tell(new ScheduleDataServiceMessage(dataService), ActorRef.noSender());
}

/** Returns a list of the uuids of the assets that expect external data */
protected List<UUID> getDataAssets() {
return extDataMapping.values().stream().toList();
}

/**
* Method to remap the data from the externally used {@link String} to {@link UUID} used by
* SIMONA.
*
* @param inputMap map: string to value
* @return map: uuid to value
*/
@SuppressWarnings("unchecked")
protected Map<UUID, V> convert(Map<String, Value> inputMap) {
Map<UUID, V> valueMap = new HashMap<>();
inputMap.entrySet().stream()
.filter(e -> extDataMapping.containsKey(e.getKey()))
.forEach(e -> valueMap.put(extDataMapping.get(e.getKey()), (V) e.getValue()));
return valueMap;
}
}
62 changes: 18 additions & 44 deletions src/main/java/edu/ie3/simona/api/data/em/ExtEmDataConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,48 @@

import edu.ie3.datamodel.models.value.PValue;
import edu.ie3.datamodel.models.value.Value;
import edu.ie3.simona.api.data.ExtInputDataConnection;
import edu.ie3.simona.api.data.ExtInputDataConnectionWithMapping;
import edu.ie3.simona.api.data.em.ontology.EmDataMessageFromExt;
import edu.ie3.simona.api.data.em.ontology.ProvideEmSetPointData;
import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.pekko.actor.ActorRef;
import org.slf4j.Logger;

/** Enables data connection of em data between SIMONA and SimonaAPI */
public class ExtEmDataConnection implements ExtInputDataConnection {

/** Actor reference to service that handles ev data within SIMONA */
private ActorRef emDataService;

/** Actor reference to adapter that handles scheduler control flow in SIMONA */
private ActorRef extSimAdapter;

/** Assets that provide primary data to SIMONA */
private final Map<String, UUID> extEmMapping;
public class ExtEmDataConnection
extends ExtInputDataConnectionWithMapping<EmDataMessageFromExt, PValue> {

public ExtEmDataConnection(Map<String, UUID> extEmMapping) {
this.extEmMapping = extEmMapping;
super(extEmMapping);
}

@Override
public void setActorRefs(ActorRef emDataService, ActorRef extSimAdapter) {
this.emDataService = emDataService;
this.extSimAdapter = extSimAdapter;
/** Returns a list of the uuids of the em agents that expect external set points */
public List<UUID> getControlledEms() {
return getDataAssets();
}

/**
* Converts the data and sends them to SIMONA.
*
* @param tick current tick
* @param data to be converted and send
* @param maybeNextTick option for the next tick in the simulation
* @param log logger
*/
public void convertAndSend(
long tick, Map<String, Value> data, Optional<Long> maybeNextTick, Logger log) {
// filtering the data and converting the keys
Map<UUID, PValue> convertedMap =
data.entrySet().stream()
.filter(e -> extEmMapping.containsKey(e.getKey()))
.collect(
Collectors.toMap(e -> extEmMapping.get(e.getKey()), e -> (PValue) e.getValue()));
Map<UUID, PValue> convertedMap = convert(data);

if (convertedMap.isEmpty()) {
log.warn("No em data found! Sending no em data to SIMONA for tick {}.", tick);
} else {
log.debug("Provided SIMONA with em data.");
provideEmData(tick, convertedMap, maybeNextTick);
provideData(tick, convertedMap, maybeNextTick);
}
}

/** Returns a list of the uuids of the em agents that expect external set points */
public List<UUID> getControlledEms() {
return extEmMapping.values().stream().toList();
}

/** Provide primary data from an external simulation for one tick. */
public void provideEmData(Long tick, Map<UUID, PValue> emData, Optional<Long> maybeNextTick) {
public void provideData(long tick, Map<UUID, PValue> emData, Optional<Long> maybeNextTick) {
sendExtMsg(new ProvideEmSetPointData(tick, emData, maybeNextTick));
}

/**
* Send information from the external simulation to SIMONA's external primary data service.
* Furthermore, ExtSimAdapter within SIMONA is instructed to activate the ev data service with the
* current tick.
*
* @param msg the data/information that is sent to SIMONA's external primary data service
*/
public void sendExtMsg(EmDataMessageFromExt msg) {
emDataService.tell(msg, ActorRef.noSender());
// we need to schedule data receiver activation with scheduler
extSimAdapter.tell(new ScheduleDataServiceMessage(emDataService), ActorRef.noSender());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,75 +7,59 @@
package edu.ie3.simona.api.data.primarydata;

import edu.ie3.datamodel.models.value.Value;
import edu.ie3.simona.api.data.ExtInputDataConnection;
import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage;
import edu.ie3.simona.api.data.ExtInputDataConnectionWithMapping;
import edu.ie3.simona.api.data.primarydata.ontology.PrimaryDataMessageFromExt;
import edu.ie3.simona.api.data.primarydata.ontology.ProvidePrimaryData;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.pekko.actor.ActorRef;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.slf4j.Logger;

/** Enables data connection of primary data between SIMONA and SimonaAPI */
public class ExtPrimaryDataConnection implements ExtInputDataConnection {
public class ExtPrimaryDataConnection
extends ExtInputDataConnectionWithMapping<PrimaryDataMessageFromExt, Value> {

/** Actor reference to service that handles primary data within SIMONA */
private ActorRef dataService;
private Map<UUID, Class<Value>> valueClasses;

/** Actor reference to adapter that handles scheduler control flow in SIMONA */
private ActorRef extSimAdapter;
public ExtPrimaryDataConnection(Map<String, UUID> extPrimaryDataMapping) {
super(extPrimaryDataMapping);
}

/** Assets that provide primary data to SIMONA */
private final Map<String, UUID> extPrimaryDataMapping;
public void setValueClasses(Map<UUID, Class<Value>> valueClasses) {
this.valueClasses = valueClasses;
}

public ExtPrimaryDataConnection(Map<String, UUID> extPrimaryDataMapping) {
this.extPrimaryDataMapping = extPrimaryDataMapping;
/** Returns a list of the uuids of the system participants that expect external primary data */
public List<UUID> getPrimaryDataAssets() {
return getDataAssets();
}

@Override
public void setActorRefs(ActorRef dataService, ActorRef extSimAdapter) {
this.dataService = dataService;
this.extSimAdapter = extSimAdapter;
/**
* @param uuid of the model
* @return an option for the value class associated with the model.
*/
public Optional<Class<Value>> getValueClass(UUID uuid) {
return Optional.ofNullable(valueClasses.get(uuid));
}

@Override
public void convertAndSend(
long tick, Map<String, Value> data, Optional<Long> maybeNextTick, Logger log) {
// filtering the data and converting the keys
Map<UUID, Value> convertedMap =
data.entrySet().stream()
.filter(e -> extPrimaryDataMapping.containsKey(e.getKey()))
.collect(
Collectors.toMap(e -> extPrimaryDataMapping.get(e.getKey()), Map.Entry::getValue));
Map<UUID, Value> convertedMap = convert(data);

if (convertedMap.isEmpty()) {
log.warn("No primary data found! Sending no primary data to SIMONA for tick {}.", tick);
} else {
log.debug("Provided SIMONA with primary data.");
providePrimaryData(tick, convertedMap, maybeNextTick);
provideData(tick, convertedMap, maybeNextTick);
}
}

/** Returns a list of the uuids of the system participants that expect external primary data */
public List<UUID> getPrimaryDataAssets() {
return extPrimaryDataMapping.values().stream().toList();
}

/** Provide primary data from an external simulation in one tick. */
public void providePrimaryData(
Long tick, Map<UUID, Value> primaryData, Optional<Long> maybeNextTick) {
@Override
public void provideData(long tick, Map<UUID, Value> primaryData, Optional<Long> maybeNextTick) {
sendExtMsg(new ProvidePrimaryData(tick, primaryData, maybeNextTick));
}

/**
* Send information from the external simulation to SIMONA's external primary data service.
* Furthermore, ExtSimAdapter within SIMONA is instructed to activate the ev data service with the
* current tick.
*
* @param msg the data/information that is sent to SIMONA's external primary data service
*/
public void sendExtMsg(PrimaryDataMessageFromExt msg) {
dataService.tell(msg, ActorRef.noSender());
// we need to schedule data receiver activation with scheduler
extSimAdapter.tell(new ScheduleDataServiceMessage(dataService), ActorRef.noSender());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import edu.ie3.datamodel.models.result.ModelResultEntity;
import edu.ie3.datamodel.models.result.NodeResult;
import edu.ie3.datamodel.models.result.ResultEntity;
import edu.ie3.datamodel.models.result.connector.LineResult;
import edu.ie3.datamodel.models.result.system.SystemParticipantResult;
import edu.ie3.simona.api.data.ExtDataContainer;
Expand Down Expand Up @@ -64,8 +65,14 @@ public Optional<Long> getNextTick() {
return maybeNextTick;
}

/** Returns the result for a certain asset. */
public ResultEntity getResult(String assetId) {
return simonaResultsMap.get(assetId);
}

/**
* Returns the voltage deviation for certain asset, if this asset provided a {@link NodeResult}
* Returns the voltage deviation in pu for certain asset, if this asset provided a {@link
* NodeResult}
*/
public double getVoltageDeviation(String assetId) {
if (simonaResultsMap.get(assetId) instanceof NodeResult nodeResult) {
Expand All @@ -77,6 +84,17 @@ public double getVoltageDeviation(String assetId) {
}
}

/**
* Returns the voltage deviation for certain asset, if this asset provided a {@link NodeResult}
*/
public double getVoltage(String assetId) {
if (simonaResultsMap.get(assetId) instanceof NodeResult nodeResult) {
return nodeResult.getvMag().getValue().doubleValue();
} else {
throw new IllegalArgumentException("VOLTAGE is only available for NodeResult's!");
}
}

/**
* Returns the active power in kW for certain asset, if this asset provided a {@link
* SystemParticipantResult}
Expand Down
Loading