diff --git a/src/main/java/edu/ie3/datamodel/io/factory/FactoryData.java b/src/main/java/edu/ie3/datamodel/io/factory/FactoryData.java index 5fc5d8afd..835674ea9 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/FactoryData.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/FactoryData.java @@ -137,6 +137,26 @@ field, getField(field)), } } + /** + * Parses and returns an array of UUIDs from field value of given field name. Throws {@link + * FactoryException} if field does not exist or parsing fails. + * + * @param field field name + * @return UUID + */ + public UUID[] getUUIDs(String field) { + try { + String[] uuidFields = field.split(" "); + return Arrays.stream(uuidFields).map(UUID::fromString).toArray(UUID[]::new); + } catch (IllegalArgumentException iae) { + throw new FactoryException( + String.format( + "Exception while trying to parse UUIDs of field \"%s\" with value \"%s\"", + field, getField(field)), + iae); + } + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EmInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EmInputFactory.java new file mode 100644 index 000000000..24a8ee8de --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EmInputFactory.java @@ -0,0 +1,67 @@ +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.io.factory.input.participant; + +import edu.ie3.datamodel.exceptions.ParsingException; +import edu.ie3.datamodel.io.factory.input.NodeAssetInputEntityData; +import edu.ie3.datamodel.models.ControlStrategy; +import edu.ie3.datamodel.models.OperationTime; +import edu.ie3.datamodel.models.input.NodeInput; +import edu.ie3.datamodel.models.input.OperatorInput; +import edu.ie3.datamodel.models.input.system.EmInput; +import edu.ie3.datamodel.models.input.system.characteristic.ReactivePowerCharacteristic; +import java.util.UUID; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EmInputFactory + extends SystemParticipantInputEntityFactory { + private static final Logger logger = LoggerFactory.getLogger(EmInputFactory.class); + + private static final String CONNECTED_ASSETS = "connectedassets"; + + private static final String CONTROL_STRATEGY = "controlstrategy"; + + public EmInputFactory() { + super(EmInput.class); + } + + @Override + protected String[] getAdditionalFields() { + return new String[] {CONNECTED_ASSETS, CONTROL_STRATEGY}; + } + + @Override + protected EmInput buildModel( + NodeAssetInputEntityData data, + UUID uuid, + String id, + NodeInput node, + ReactivePowerCharacteristic qCharacteristics, + OperatorInput operator, + OperationTime operationTime) { + ControlStrategy controlStrategy; + try { + controlStrategy = ControlStrategy.parse(data.getField(CONTROL_STRATEGY)); + } catch (ParsingException e) { + logger.warn( + "Cannot parse control strategy \"{}\" of energy management system \"{}\". Assign no control strategy instead.", + data.getField(CONTROL_STRATEGY), + id); + controlStrategy = ControlStrategy.DefaultControlStrategies.NO_CONTROL_STRATEGY; + } + final UUID[] connectedAssets = data.getUUIDs(data.getField(CONNECTED_ASSETS)); + return new EmInput( + uuid, + id, + operator, + operationTime, + node, + qCharacteristics, + connectedAssets, + controlStrategy); + } +} diff --git a/src/main/java/edu/ie3/datamodel/io/processor/Processor.java b/src/main/java/edu/ie3/datamodel/io/processor/Processor.java index d998f7ff2..48b1cd597 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/Processor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/Processor.java @@ -8,6 +8,7 @@ import edu.ie3.datamodel.exceptions.EntityProcessorException; import edu.ie3.datamodel.io.factory.input.NodeInputFactory; import edu.ie3.datamodel.io.processor.result.ResultEntityProcessor; +import edu.ie3.datamodel.models.ControlStrategy; import edu.ie3.datamodel.models.OperationTime; import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.UniqueEntity; @@ -269,6 +270,9 @@ protected String processMethodResult(Object methodReturnObject, Method method, S "ReactivePowerCharacteristic", "CharacteristicInput" -> resultStringBuilder.append( ((CharacteristicInput) methodReturnObject).deSerialize()); + case "UUID[]" -> resultStringBuilder.append(processUUIDArray((UUID[]) methodReturnObject)); + case "ControlStrategy" -> resultStringBuilder.append( + ((ControlStrategy) methodReturnObject).getKey()); default -> throw new EntityProcessorException( "Unable to process value for attribute/field '" + fieldName @@ -327,6 +331,28 @@ protected String handleQuantity(Quantity quantity, String fieldName) { + ".class.")); } + /** + * This method should handle all quantities that are model processor specific e.g. we need to + * handle active power p different for {@link edu.ie3.datamodel.models.result.ResultEntity}s and + * {@link edu.ie3.datamodel.models.input.system.SystemParticipantInput}s Hence from the + * generalized method {@link #handleQuantity(Quantity, String)}, this allows for the specific + * handling of child implementations. See the implementation @ {@link ResultEntityProcessor} for + * details. + * + * @param quantity the quantity that should be processed + * @param fieldName the field name the quantity is set to + * @return an optional string with the normalized to {@link StandardUnits} value of the quantity + * or empty if an error occurred during processing + */ + protected abstract Optional handleProcessorSpecificQuantity( + Quantity quantity, String fieldName); + + protected String processUUIDArray(UUID[] uuids) { + StringBuilder strb = new StringBuilder(); + for (UUID uuid : uuids) strb.append(uuid.toString()).append(" "); + return strb.toString().strip(); + } + /** * Handling of elements of type {@link OperationTime} * @@ -363,22 +389,6 @@ protected String processZonedDateTime(ZonedDateTime zonedDateTime) { return zonedDateTime.toString(); } - /** - * This method should handle all quantities that are model processor specific e.g. we need to - * handle active power p different for {@link edu.ie3.datamodel.models.result.ResultEntity}s and - * {@link edu.ie3.datamodel.models.input.system.SystemParticipantInput}s Hence from the - * generalized method {@link #handleQuantity(Quantity, String)}, this allows for the specific - * handling of child implementations. See the implementation @ {@link ResultEntityProcessor} for - * details. - * - * @param quantity the quantity that should be processed - * @param fieldName the field name the quantity is set to - * @return an optional string with the normalized to {@link StandardUnits} value of the quantity - * or empty if an error occurred during processing - */ - protected abstract Optional handleProcessorSpecificQuantity( - Quantity quantity, String fieldName); - /** * Converts a given quantity to String by extracting the value and applying the toString method to * it diff --git a/src/main/java/edu/ie3/datamodel/io/processor/input/InputEntityProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/input/InputEntityProcessor.java index 1ab8a66b7..16a75b725 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/input/InputEntityProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/input/InputEntityProcessor.java @@ -55,6 +55,7 @@ public class InputEntityProcessor extends EntityProcessor { PvInput.class, StorageInput.class, WecInput.class, + EmInput.class, /* -- ThermalUnitInput */ ThermalHouseInput.class, CylindricalStorageInput.class, diff --git a/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java b/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java index ff9a1aa04..3a742ca49 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java @@ -390,4 +390,35 @@ Set getHeatPumps( Set operators, Set types, Set thermalBuses); + + /** + * Returns a unique set of {@link EmInput} instances. + * + *

This set has to be unique in the sense of object uniqueness but also in the sense of {@link + * java.util.UUID} uniqueness of the provided {@link EmInput} which has to be checked manually, as + * {@link EmInput#equals(Object)} is NOT restricted on the uuid of {@link EmInput}. + * + * @return a set of object and uuid unique {@link EmInput} entities + */ + Set getEmSystems(); + + /** + * This set has to be unique in the sense of object uniqueness but also in the sense of {@link + * java.util.UUID} uniqueness of the provided {@link EmInput} which has to be checked manually, as + * {@link EmInput#equals(Object)} is NOT restricted on the uuid of {@link EmInput}. + * + *

In contrast to {@link #getHeatPumps()} this interface provides the ability to pass in an + * already existing set of {@link NodeInput} and {@link OperatorInput} entities, the {@link + * EmInput} instances depend on. Doing so, already loaded nodes can be recycled to improve + * performance and prevent unnecessary loading operations. + * + *

If something fails during the creation process it's up to the concrete implementation of an + * empty set or a set with all entities that has been able to be build is returned. + * + * @param operators a set of object and uuid unique {@link OperatorInput} that should be used for + * the returning instances + * @param nodes a set of object and uuid unique {@link NodeInput} entities + * @return a set of object and uuid unique {@link EmInput} entities + */ + Set getEmSystems(Set nodes, Set operators); } diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSource.java index 80bc725e3..58b0e5c71 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSource.java @@ -63,6 +63,7 @@ public class CsvSystemParticipantSource extends CsvDataSource implements SystemP private final StorageInputFactory storageInputFactory; private final WecInputFactory wecInputFactory; private final EvcsInputFactory evcsInputFactory; + private final EmInputFactory emInputFactory; public CsvSystemParticipantSource( String csvSep, @@ -87,6 +88,7 @@ public CsvSystemParticipantSource( this.storageInputFactory = new StorageInputFactory(); this.wecInputFactory = new WecInputFactory(); this.evcsInputFactory = new EvcsInputFactory(); + this.emInputFactory = new EmInputFactory(); } /** {@inheritDoc} */ @@ -168,6 +170,11 @@ public Optional getSystemParticipants() { .filter(isPresentCollectIfNot(HpInput.class, nonBuildEntities)) .map(Optional::get) .collect(Collectors.toSet()); + Set emInputs = + nodeAssetEntityStream(EmInput.class, emInputFactory, nodes, operators) + .filter(isPresentCollectIfNot(EmInput.class, nonBuildEntities)) + .map(Optional::get) + .collect(Collectors.toSet()); // if we found invalid elements return an empty optional and log the problems if (!nonBuildEntities.isEmpty()) { @@ -187,7 +194,8 @@ public Optional getSystemParticipants() { loads, pvInputs, storages, - wecInputs)); + wecInputs, + emInputs)); } /** {@inheritDoc} */ @@ -637,7 +645,7 @@ private Optional buildHpEntityData( // if the requested entity is not present we return an empty element and // log a warning - if (!hpInputEntityDataOpt.isPresent()) { + if (hpInputEntityDataOpt.isEmpty()) { logSkippingWarning( typedEntityData.getTargetClass().getSimpleName(), saveMapGet(fieldsToAttributes, "uuid", FIELDS_TO_VALUES_MAP), @@ -732,4 +740,29 @@ private Optional buildChpEntityData( thermalBus.get(), thermalStorage.get())); } + + @Override + public Set getEmSystems() { + Set operators = typeSource.getOperators(); + return getEmSystems(rawGridSource.getNodes(operators), operators); + } + + /** + * {@inheritDoc} + * + *

If the set of {@link NodeInput} entities is not exhaustive for all available {@link + * LoadInput} entities (e.g. a {@link NodeInput} entity is missing) or if an error during the + * building process occurs, the entity that misses something will be skipped (which can be seen as + * a filtering functionality), but all entities that are able to be built will be returned anyway + * and the elements that couldn't have been built are logged. + * + *

If the set with {@link OperatorInput} is not exhaustive, the corresponding operator is set + * to {@link OperatorInput#NO_OPERATOR_ASSIGNED} + */ + @Override + public Set getEmSystems(Set nodes, Set operators) { + return nodeAssetEntityStream(EmInput.class, emInputFactory, nodes, operators) + .flatMap(Optional::stream) + .collect(Collectors.toSet()); + } } diff --git a/src/main/java/edu/ie3/datamodel/models/ControlStrategy.java b/src/main/java/edu/ie3/datamodel/models/ControlStrategy.java new file mode 100644 index 000000000..61ad82ddf --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/ControlStrategy.java @@ -0,0 +1,35 @@ +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models; + +import edu.ie3.datamodel.exceptions.ParsingException; +import java.io.Serializable; +import java.util.Arrays; + +public interface ControlStrategy extends Serializable { + String getKey(); + + static ControlStrategy parse(String key) throws ParsingException { + if (key == null || key.isEmpty()) + return ControlStrategy.DefaultControlStrategies.NO_CONTROL_STRATEGY; + + String filterKey = key.toLowerCase().replace("-", "_"); + return Arrays.stream(EmControlStrategy.values()) + .filter(profile -> profile.getKey().equals(filterKey)) + .findFirst() + .orElseThrow( + () -> new ParsingException("Cannot parse \"" + key + "\" to a valid control strategy")); + } + + enum DefaultControlStrategies implements ControlStrategy { + NO_CONTROL_STRATEGY; + + @Override + public String getKey() { + return "No control strategy assigned"; + } + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/EmControlStrategy.java b/src/main/java/edu/ie3/datamodel/models/EmControlStrategy.java new file mode 100644 index 000000000..ffb216a35 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/EmControlStrategy.java @@ -0,0 +1,45 @@ +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models; + +import java.util.Arrays; +import java.util.Locale; +import java.util.stream.Collectors; + +public enum EmControlStrategy implements ControlStrategy { + SELF_OPTIMIZATION("self_optimization"); + + private final String key; + + EmControlStrategy(String key) { + this.key = key.toLowerCase(Locale.ROOT); + } + + public static EmControlStrategy get(String key) { + return Arrays.stream(EmControlStrategy.values()) + .filter(controlStrategy -> controlStrategy.key.equalsIgnoreCase(key)) + .findFirst() + .orElseThrow( + () -> + new IllegalArgumentException( + "No predefined energy management control strategy '" + + key + + "' found. Please provide one of the following keys: " + + Arrays.stream(EmControlStrategy.values()) + .map(EmControlStrategy::getKey) + .collect(Collectors.joining(", ")))); + } + + @Override + public String getKey() { + return key; + } + + @Override + public String toString() { + return "EmControlStrategy{" + "key='" + key + '\'' + '}'; + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/input/container/SystemParticipants.java b/src/main/java/edu/ie3/datamodel/models/input/container/SystemParticipants.java index 9067b5a2c..f08be2cd3 100644 --- a/src/main/java/edu/ie3/datamodel/models/input/container/SystemParticipants.java +++ b/src/main/java/edu/ie3/datamodel/models/input/container/SystemParticipants.java @@ -24,6 +24,7 @@ public class SystemParticipants implements InputContainer pvPlants; private final Set storages; private final Set wecPlants; + private final Set emSystems; public SystemParticipants( Set bmPlants, @@ -35,7 +36,8 @@ public SystemParticipants( Set loads, Set pvPlants, Set storages, - Set wecPlants) { + Set wecPlants, + Set emSystems) { this.bmPlants = bmPlants; this.chpPlants = chpPlants; this.evCS = evCS; @@ -46,6 +48,7 @@ public SystemParticipants( this.pvPlants = pvPlants; this.storages = storages; this.wecPlants = wecPlants; + this.emSystems = emSystems; } /** @@ -94,6 +97,10 @@ public SystemParticipants(Collection systemParticipants) { systemParticipants.stream() .flatMap(participants -> participants.wecPlants.stream()) .collect(Collectors.toSet()); + this.emSystems = + systemParticipants.stream() + .flatMap(participants -> participants.emSystems.stream()) + .collect(Collectors.toSet()); } /** @@ -155,6 +162,11 @@ public SystemParticipants(List systemParticipants) { .filter(WecInput.class::isInstance) .map(WecInput.class::cast) .collect(Collectors.toSet()); + this.emSystems = + systemParticipants.parallelStream() + .filter(EmInput.class::isInstance) + .map(EmInput.class::cast) + .collect(Collectors.toSet()); } @Override @@ -223,6 +235,10 @@ public Set getWecPlants() { return Collections.unmodifiableSet(wecPlants); } + public Set getEmSystems() { + return Collections.unmodifiableSet(emSystems); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/edu/ie3/datamodel/models/input/system/EmInput.java b/src/main/java/edu/ie3/datamodel/models/input/system/EmInput.java new file mode 100644 index 000000000..42329dc07 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/input/system/EmInput.java @@ -0,0 +1,213 @@ +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.models.input.system; + +import edu.ie3.datamodel.models.ControlStrategy; +import edu.ie3.datamodel.models.EmControlStrategy; +import edu.ie3.datamodel.models.OperationTime; +import edu.ie3.datamodel.models.input.NodeInput; +import edu.ie3.datamodel.models.input.OperatorInput; +import edu.ie3.datamodel.models.input.system.characteristic.ReactivePowerCharacteristic; +import java.util.Arrays; +import java.util.Objects; +import java.util.UUID; + +public class EmInput extends SystemParticipantInput { + + /** Reference via UUID to all SystemParticipantInputs connected to this model */ + private final UUID[] connectedAssets; + + /** Reference to the control strategy to be used for this model */ + private final ControlStrategy controlStrategy; + /** + * Constructor for an operated energy management system + * + * @param uuid of the input entity + * @param id of the asset + * @param operator of the asset + * @param operationTime time for which the entity is operated + * @param node the asset is connected to + * @param qCharacteristics description of a reactive power characteristic + * @param connectedAssets array of all connected assets + * @param controlStrategy control strategy used for this model + */ + public EmInput( + UUID uuid, + String id, + OperatorInput operator, + OperationTime operationTime, + NodeInput node, + ReactivePowerCharacteristic qCharacteristics, + UUID[] connectedAssets, + ControlStrategy controlStrategy) { + super(uuid, id, operator, operationTime, node, qCharacteristics); + this.connectedAssets = connectedAssets; + this.controlStrategy = controlStrategy; + } + + /** + * Constructor for an operated energy management system + * + * @param uuid of the input entity + * @param id of the asset + * @param operator of the asset + * @param operationTime time for which the entity is operated + * @param node the asset is connected to + * @param qCharacteristics description of a reactive power characteristic + * @param connectedAssets array of all connected assets + * @param emControlStrategy {@link edu.ie3.datamodel.models.EmControlStrategy} control strategy + * key + */ + public EmInput( + UUID uuid, + String id, + OperatorInput operator, + OperationTime operationTime, + NodeInput node, + ReactivePowerCharacteristic qCharacteristics, + UUID[] connectedAssets, + String emControlStrategy) { + super(uuid, id, operator, operationTime, node, qCharacteristics); + this.connectedAssets = connectedAssets; + this.controlStrategy = EmControlStrategy.get(emControlStrategy); + } + + /** + * Constructor for an operated energy management system + * + * @param uuid of the input entity + * @param id of the asset + * @param node the asset is connected to + * @param qCharacteristics description of a reactive power characteristic + * @param connectedAssets array of all connected assets + * @param controlStrategy control strategy used for this model + */ + public EmInput( + UUID uuid, + String id, + NodeInput node, + ReactivePowerCharacteristic qCharacteristics, + UUID[] connectedAssets, + ControlStrategy controlStrategy) { + super(uuid, id, node, qCharacteristics); + this.connectedAssets = connectedAssets; + this.controlStrategy = controlStrategy; + } + + /** + * Constructor for an operated energy management system + * + * @param uuid of the input entity + * @param id of the asset + * @param node the asset is connected to + * @param qCharacteristics description of a reactive power characteristic + * @param connectedAssets array of all connected assets + * @param emControlStrategy {@link edu.ie3.datamodel.models.EmControlStrategy} control strategy + * key + */ + public EmInput( + UUID uuid, + String id, + NodeInput node, + ReactivePowerCharacteristic qCharacteristics, + UUID[] connectedAssets, + String emControlStrategy) { + super(uuid, id, node, qCharacteristics); + this.connectedAssets = connectedAssets; + this.controlStrategy = EmControlStrategy.get(emControlStrategy); + } + + public UUID[] getConnectedAssets() { + return connectedAssets; + } + + public ControlStrategy getControlStrategy() { + return controlStrategy; + } + + @Override + public EmInputCopyBuilder copy() { + return new EmInputCopyBuilder(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof EmInput emInput)) return false; + if (!super.equals(o)) return false; + return Arrays.equals(connectedAssets, emInput.connectedAssets) + && controlStrategy == emInput.controlStrategy; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), Arrays.hashCode(connectedAssets), controlStrategy); + } + + @Override + public String toString() { + return "EmInput{" + + "uuid=" + + getUuid() + + ", id='" + + getId() + + ", operator=" + + getOperator().getUuid() + + ", operationTime=" + + getOperationTime() + + ", node=" + + getNode().getUuid() + + ", qCharacteristics='" + + getqCharacteristics() + + ", connectedAssets=" + + Arrays.toString(connectedAssets) + + ", controlStrategy=" + + controlStrategy + + '}'; + } + + public static class EmInputCopyBuilder + extends SystemParticipantInputCopyBuilder { + + private UUID[] connectedAssets; + + private ControlStrategy controlStrategy; + + protected EmInputCopyBuilder(EmInput entity) { + super(entity); + this.connectedAssets = entity.getConnectedAssets(); + this.controlStrategy = entity.getControlStrategy(); + } + + public EmInputCopyBuilder connectedAssets(UUID[] connectedAssets) { + this.connectedAssets = connectedAssets; + return this; + } + + public EmInputCopyBuilder controlStrategy(ControlStrategy controlStrategy) { + this.controlStrategy = controlStrategy; + return this; + } + + @Override + public EmInput build() { + return new EmInput( + getUuid(), + getId(), + getOperator(), + getOperationTime(), + getNode(), + getqCharacteristics(), + connectedAssets, + controlStrategy); + } + + @Override + protected EmInputCopyBuilder childInstance() { + return this; + } + } +} diff --git a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java index 4166794fe..6470290f1 100644 --- a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java @@ -366,6 +366,7 @@ public static SystemParticipants filterForSubnet(SystemParticipants input, int s Set pvs = filterParticipants(input.getPvPlants(), subnet); Set storages = filterParticipants(input.getStorages(), subnet); Set wecPlants = filterParticipants(input.getWecPlants(), subnet); + Set emSystems = filterParticipants(input.getEmSystems(), subnet); return new SystemParticipants( bmPlants, @@ -377,7 +378,8 @@ public static SystemParticipants filterForSubnet(SystemParticipants input, int s loads, pvs, storages, - wecPlants); + wecPlants, + emSystems); } /** diff --git a/src/test/groovy/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategyTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategyTest.groovy index 7e32d0caf..b0ae57ff6 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategyTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/naming/EntityPersistenceNamingStrategyTest.groovy @@ -21,6 +21,7 @@ import edu.ie3.datamodel.models.input.graphics.LineGraphicInput import edu.ie3.datamodel.models.input.graphics.NodeGraphicInput import edu.ie3.datamodel.models.input.system.BmInput import edu.ie3.datamodel.models.input.system.ChpInput +import edu.ie3.datamodel.models.input.system.EmInput import edu.ie3.datamodel.models.input.system.EvInput import edu.ie3.datamodel.models.input.system.EvcsInput import edu.ie3.datamodel.models.input.system.FixedFeedInInput @@ -309,6 +310,7 @@ class EntityPersistenceNamingStrategyTest extends Specification { Transformer3WInput || "transformer_3_w_input" CylindricalStorageInput || "cylindrical_storage_input" ThermalHouseInput || "thermal_house_input" + EmInput || "em_input" } def "A EntityPersistenceNamingStrategy without pre- or suffixes should return valid strings for all input types models"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/processor/ProcessorProviderTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/processor/ProcessorProviderTest.groovy index 79140754a..5f436cc68 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/processor/ProcessorProviderTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/processor/ProcessorProviderTest.groovy @@ -82,6 +82,7 @@ class ProcessorProviderTest extends Specification implements TimeSeriesTestData PvInput, StorageInput, WecInput, + EmInput, /* -- ThermalUnitInput */ ThermalHouseInput, CylindricalStorageInput, diff --git a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy index 80a5f386d..b835bb530 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/sink/CsvFileSinkTest.groovy @@ -5,10 +5,11 @@ */ package edu.ie3.datamodel.io.sink -import static edu.ie3.util.quantities.PowerSystemUnits.DEGREE_GEOM import static edu.ie3.util.quantities.PowerSystemUnits.KILOVOLTAMPERE import static tech.units.indriya.unit.Units.PERCENT - +import static edu.ie3.util.quantities.PowerSystemUnits.DEGREE_GEOM +import edu.ie3.datamodel.models.input.system.EmInput +import edu.ie3.datamodel.models.input.system.LoadInput import edu.ie3.datamodel.io.naming.FileNamingStrategy import edu.ie3.datamodel.io.processor.ProcessorProvider import edu.ie3.datamodel.io.processor.input.InputEntityProcessor @@ -139,27 +140,29 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { def "A valid CsvFileSink without 'initFiles' should only persist provided elements correctly but not init all files"() { given: CsvFileSink csvFileSink = new CsvFileSink(testBaseFolderPath, - new ProcessorProvider([ - new ResultEntityProcessor(PvResult), - new ResultEntityProcessor(WecResult), - new ResultEntityProcessor(EvResult), - new ResultEntityProcessor(EvcsResult), - new InputEntityProcessor(Transformer2WInput), - new InputEntityProcessor(NodeInput), - new InputEntityProcessor(EvcsInput), - new InputEntityProcessor(Transformer2WTypeInput), - new InputEntityProcessor(LineGraphicInput), - new InputEntityProcessor(NodeGraphicInput), - new InputEntityProcessor(CylindricalStorageInput), - new InputEntityProcessor(ThermalHouseInput), - new InputEntityProcessor(OperatorInput), - new InputEntityProcessor(LineInput), - new InputEntityProcessor(ThermalBusInput), - new InputEntityProcessor(LineTypeInput) - ], [] as Map), - new FileNamingStrategy(), - false, - ",") + new ProcessorProvider([ + new ResultEntityProcessor(PvResult), + new ResultEntityProcessor(WecResult), + new ResultEntityProcessor(EvResult), + new ResultEntityProcessor(EvcsResult), + new InputEntityProcessor(Transformer2WInput), + new InputEntityProcessor(NodeInput), + new InputEntityProcessor(EvcsInput), + new InputEntityProcessor(Transformer2WTypeInput), + new InputEntityProcessor(LineGraphicInput), + new InputEntityProcessor(NodeGraphicInput), + new InputEntityProcessor(CylindricalStorageInput), + new InputEntityProcessor(ThermalHouseInput), + new InputEntityProcessor(OperatorInput), + new InputEntityProcessor(LineInput), + new InputEntityProcessor(ThermalBusInput), + new InputEntityProcessor(LineTypeInput), + new InputEntityProcessor(LoadInput), + new InputEntityProcessor(EmInput) + ], [] as Map), + new FileNamingStrategy(), + false, + ",") UUID uuid = UUID.fromString("22bea5fc-2cb2-4c61-beb9-b476e0107f52") UUID inputModel = UUID.fromString("22bea5fc-2cb2-4c61-beb9-b476e0107f52") @@ -179,7 +182,9 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { GridTestData.nodeGraphicC, ThermalUnitInputTestData.cylindricStorageInput, ThermalUnitInputTestData.thermalHouseInput, - SystemParticipantTestData.evcsInput + SystemParticipantTestData.evcsInput, + SystemParticipantTestData.loadInput, + SystemParticipantTestData.emInput ]) csvFileSink.shutdown() @@ -199,6 +204,8 @@ class CsvFileSinkTest extends Specification implements TimeSeriesTestData { new File(testBaseFolderPath + File.separator + "node_graphic_input.csv").exists() new File(testBaseFolderPath + File.separator + "thermal_bus_input.csv").exists() new File(testBaseFolderPath + File.separator + "thermal_house_input.csv").exists() + new File(testBaseFolderPath + File.separator + "load_input.csv").exists() + new File(testBaseFolderPath + File.separator + "em_input.csv").exists() !new File(testBaseFolderPath + File.separator + "ev_res.csv").exists() } diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSourceTest.groovy index a805e8ede..f010f6d13 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSourceTest.groovy @@ -55,6 +55,7 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat assert (systemParticipants.getWecPlants().first().uuid == sptd.wecInput.uuid) assert (systemParticipants.getStorages().first().uuid == sptd.storageInput.uuid) assert (systemParticipants.getEvCS().first().uuid == sptd.evcsInput.uuid) + assert (systemParticipants.getEmSystems().first().uuid == sptd.emInput.uuid) }) } @@ -382,4 +383,21 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat ] as List || 0 || [] []| [] as List || 0 || [] } + + def "A CsvSystemParticipantSource should return data from valid em input file as expected"() { + given: + def csvSystemParticipantSource = new CsvSystemParticipantSource(csvSep, participantsFolderPath, + fileNamingStrategy, Mock(CsvTypeSource), Mock(CsvThermalSource), Mock(CsvRawGridSource)) + + expect: + def sysParts = csvSystemParticipantSource.getEmSystems(nodes as Set, operators as Set) + sysParts.size() == resultingSize + sysParts == resultingSet as Set + + where: + nodes | operators || resultingSize || resultingSet + [sptd.emInput.node] | [sptd.emInput.operator] || 1 || [sptd.emInput] + [] | [sptd.pvInput.operator] || 0 || [] + [] | [] || 0 || [] + } } diff --git a/src/test/groovy/edu/ie3/datamodel/models/EmControlStrategyTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/EmControlStrategyTest.groovy new file mode 100644 index 000000000..d31faa42f --- /dev/null +++ b/src/test/groovy/edu/ie3/datamodel/models/EmControlStrategyTest.groovy @@ -0,0 +1,42 @@ +package edu.ie3.datamodel.models + +import edu.ie3.datamodel.exceptions.FactoryException +import edu.ie3.datamodel.io.factory.input.NodeAssetInputEntityData +import edu.ie3.datamodel.io.factory.input.participant.FixedFeedInInputFactory +import edu.ie3.datamodel.models.input.NodeInput +import edu.ie3.datamodel.models.input.system.FixedFeedInInput +import spock.lang.Specification + +import java.util.stream.Collectors + +class EmControlStrategyTest extends Specification { + + def "An em control strategy should be gotten by their key"() { + given: + EmControlStrategy actual = EmControlStrategy.get(key) + + expect: + actual == expected + + where: + key || expected + EmControlStrategy.SELF_OPTIMIZATION.getKey() || EmControlStrategy.SELF_OPTIMIZATION + + } + + def "An em control strategy should throw an exception when calling get on unkown key"() { + given: + String unknownKey = "nobody_knows_me" + + when: + EmControlStrategy _ = EmControlStrategy.get(unknownKey) + + then: + IllegalArgumentException ex = thrown() + ex.message == "No predefined energy management control strategy '" + + unknownKey + + "' found. Please provide one of the following keys: " + + Arrays.stream(EmControlStrategy.values()).map(EmControlStrategy::getKey).collect(Collectors.joining(", ")) + } + +} diff --git a/src/test/groovy/edu/ie3/datamodel/models/input/container/JointGridContainerTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/input/container/JointGridContainerTest.groovy index 24859f48d..6230486d9 100644 --- a/src/test/groovy/edu/ie3/datamodel/models/input/container/JointGridContainerTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/models/input/container/JointGridContainerTest.groovy @@ -5,9 +5,11 @@ */ package edu.ie3.datamodel.models.input.container +import static edu.ie3.test.common.SystemParticipantTestData.emptySystemParticipants import edu.ie3.test.common.GridTestData import spock.lang.Specification + class JointGridContainerTest extends Specification { private static final GRID_NAME = "single_grid" @@ -19,17 +21,6 @@ class JointGridContainerTest extends Specification { [] as Set, [] as Set) - private static final SystemParticipants SYSTEM_PARTICIPANTS = new SystemParticipants( - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set) private static final GraphicElements GRAPHIC_ELEMENTS = new GraphicElements( [] as Set, @@ -37,7 +28,7 @@ class JointGridContainerTest extends Specification { def "A single subgrid can be used to build a JointGridContainer"() { when: - def jointGridContainer = new JointGridContainer(GRID_NAME, RAW_GRID, SYSTEM_PARTICIPANTS, GRAPHIC_ELEMENTS) + def jointGridContainer = new JointGridContainer(GRID_NAME, RAW_GRID, emptySystemParticipants, GRAPHIC_ELEMENTS) then: noExceptionThrown() diff --git a/src/test/groovy/edu/ie3/datamodel/models/input/container/SystemParticipantsTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/input/container/SystemParticipantsTest.groovy index 365dfa9c9..abd2fd747 100644 --- a/src/test/groovy/edu/ie3/datamodel/models/input/container/SystemParticipantsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/models/input/container/SystemParticipantsTest.groovy @@ -13,17 +13,18 @@ class SystemParticipantsTest extends Specification { def "A valid collection of asset entities can be used to build a valid instance of SystemParticipants"() { given: def systemParticipants = new SystemParticipants( - Collections.singleton(SystemParticipantTestData.bmInput), - Collections.singleton(SystemParticipantTestData.chpInput), - Collections.emptySet(), - Collections.singleton(SystemParticipantTestData.evInput), - Collections.singleton(SystemParticipantTestData.fixedFeedInInput), - Collections.singleton(SystemParticipantTestData.hpInput), - Collections.singleton(SystemParticipantTestData.loadInput), - Collections.singleton(SystemParticipantTestData.pvInput), - Collections.singleton(SystemParticipantTestData.storageInput), - Collections.singleton(SystemParticipantTestData.wecInput) - ) + Collections.singleton(SystemParticipantTestData.bmInput), + Collections.singleton(SystemParticipantTestData.chpInput), + Collections.emptySet(), + Collections.singleton(SystemParticipantTestData.evInput), + Collections.singleton(SystemParticipantTestData.fixedFeedInInput), + Collections.singleton(SystemParticipantTestData.hpInput), + Collections.singleton(SystemParticipantTestData.loadInput), + Collections.singleton(SystemParticipantTestData.pvInput), + Collections.singleton(SystemParticipantTestData.storageInput), + Collections.singleton(SystemParticipantTestData.wecInput), + Collections.singleton(SystemParticipantTestData.emInput) + ) when: def newlyCreatedSystemParticipants = new SystemParticipants(systemParticipants.allEntitiesAsList()) diff --git a/src/test/groovy/edu/ie3/datamodel/models/input/system/EmInputTest.groovy b/src/test/groovy/edu/ie3/datamodel/models/input/system/EmInputTest.groovy new file mode 100644 index 000000000..48cfaf7bb --- /dev/null +++ b/src/test/groovy/edu/ie3/datamodel/models/input/system/EmInputTest.groovy @@ -0,0 +1,94 @@ +package edu.ie3.datamodel.models.input.system + +import static edu.ie3.datamodel.models.ControlStrategy.DefaultControlStrategies.NO_CONTROL_STRATEGY +import edu.ie3.datamodel.models.ControlStrategy +import edu.ie3.test.common.SystemParticipantTestData +import spock.lang.Specification + + +class EmInputTest extends Specification { + + def "The EmInput constructors work as expected"() { + when: + def emInput = new EmInput( + UUID.fromString("977157f4-25e5-4c72-bf34-440edc778792"), + "test_emInput", + SystemParticipantTestData.participantNode, + SystemParticipantTestData.cosPhiFixed, + SystemParticipantTestData.connectedAssets, + SystemParticipantTestData.emControlStrategy + ) + + then: + emInput.with { + assert uuid == UUID.fromString("977157f4-25e5-4c72-bf34-440edc778792") + assert id == "test_emInput" + assert qCharacteristics == SystemParticipantTestData.cosPhiFixed + assert connectedAssets == SystemParticipantTestData.connectedAssets + assert controlStrategy.key == SystemParticipantTestData.emControlStrategy + + } + } + + def "EmInputs are comparable"() { + + given: + def emInputA = SystemParticipantTestData.emInput + + expect: + (emInputA == emInputB) == isEqual + + where: + emInputB || isEqual + SystemParticipantTestData.emInput || true + SystemParticipantTestData.emInput.copy().build() || true + SystemParticipantTestData.emInput.copy().id("otherId").build() || false + } + + def "The EmInput to String method work as expected"() { + + given: + def emInputToString = SystemParticipantTestData.emInput.toString() + + expect: + emInputToString == "EmInput{" + + "uuid=" + + SystemParticipantTestData.emInput.uuid + + ", id='" + + SystemParticipantTestData.emInput.id + + ", operator=" + + SystemParticipantTestData.emInput.operator.uuid + + ", operationTime=" + + SystemParticipantTestData.emInput.operationTime + + ", node=" + + SystemParticipantTestData.emInput.node.uuid + + ", qCharacteristics='" + + SystemParticipantTestData.emInput.qCharacteristics + + ", connectedAssets=" + + Arrays.toString(SystemParticipantTestData.emInput.connectedAssets) + + ", controlStrategy=" + + SystemParticipantTestData.emInput.controlStrategy + + '}' + } + + def "A EmInput copy method should work as expected"() { + given: + def emInput = SystemParticipantTestData.emInput + def newConnectedAssets = [UUID.randomUUID(), UUID.randomUUID()] as UUID[] + + + when: + def alteredUnit = emInput.copy().connectedAssets(newConnectedAssets).controlStrategy(ControlStrategy.parse("")).build() + + then: + alteredUnit.with { + assert uuid == emInput.uuid + assert operationTime == emInput.operationTime + assert operator == emInput.operator + assert id == emInput.id + assert qCharacteristics == emInput.qCharacteristics + assert connectedAssets == newConnectedAssets + assert controlStrategy == NO_CONTROL_STRATEGY + } + } +} diff --git a/src/test/groovy/edu/ie3/test/common/ComplexTopology.groovy b/src/test/groovy/edu/ie3/test/common/ComplexTopology.groovy index 92e6c73e3..2bcae8d60 100644 --- a/src/test/groovy/edu/ie3/test/common/ComplexTopology.groovy +++ b/src/test/groovy/edu/ie3/test/common/ComplexTopology.groovy @@ -5,6 +5,7 @@ */ package edu.ie3.test.common +import static edu.ie3.test.common.SystemParticipantTestData.emptySystemParticipants import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.datamodel.graph.SubGridTopologyGraph import edu.ie3.datamodel.models.input.connector.ConnectorPort @@ -14,7 +15,6 @@ import edu.ie3.datamodel.models.input.container.RawGridElements import edu.ie3.datamodel.models.input.container.SubGridContainer import edu.ie3.datamodel.models.input.container.SystemParticipants import org.jgrapht.graph.DirectedMultigraph -import org.jgrapht.graph.SimpleDirectedGraph class ComplexTopology extends GridTestData { public static final gridName = "complex_topology" @@ -44,17 +44,7 @@ class ComplexTopology extends GridTestData { public static final grid = new JointGridContainer( gridName, rawGrid, - new SystemParticipants( - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set), + emptySystemParticipants, new GraphicElements( [] as Set, [] as Set)) @@ -84,6 +74,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set, [] as Set, + [] as Set, [] as Set), new GraphicElements( [] as Set, @@ -100,17 +91,7 @@ class ComplexTopology extends GridTestData { [transformerAtoBtoC] as Set, [] as Set, [] as Set), - new SystemParticipants( - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set), + emptySystemParticipants, new GraphicElements( [] as Set, [] as Set) @@ -126,17 +107,7 @@ class ComplexTopology extends GridTestData { [transformerAtoBtoC] as Set, [] as Set, [] as Set), - new SystemParticipants( - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set), + emptySystemParticipants, new GraphicElements( [] as Set, [] as Set) @@ -152,17 +123,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set, [] as Set), - new SystemParticipants( - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set), + emptySystemParticipants, new GraphicElements( [] as Set, [] as Set) @@ -181,17 +142,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set, [] as Set), - new SystemParticipants( - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set), + emptySystemParticipants, new GraphicElements( [] as Set, [] as Set) @@ -210,17 +161,7 @@ class ComplexTopology extends GridTestData { [] as Set, [] as Set, [] as Set), - new SystemParticipants( - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set, - [] as Set), + emptySystemParticipants, new GraphicElements( [] as Set, [] as Set) diff --git a/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy b/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy index d476b568d..b99b0d11d 100644 --- a/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy +++ b/src/test/groovy/edu/ie3/test/common/SampleJointGrid.groovy @@ -67,59 +67,59 @@ class SampleJointGrid extends SystemParticipantTestData { final PvInput pvInput = new PvInput( UUID.fromString("d56f15b7-8293-4b98-b5bd-58f6273ce229"), - "test_pvInput", - SystemParticipantTestData.operator, - SystemParticipantTestData.operationTime, + "test_pvInput", + operator, + operationTime, participantNode, - SystemParticipantTestData.cosPhiFixed, - SystemParticipantTestData.albedo, - SystemParticipantTestData.azimuth, - SystemParticipantTestData.etaConv, - SystemParticipantTestData.elevationAngle, - SystemParticipantTestData.kG, - SystemParticipantTestData.kT, - false, - SystemParticipantTestData.sRated, - SystemParticipantTestData.cosPhiRated) + cosPhiFixed, + albedo, + azimuth, + etaConv, + elevationAngle, + kG, + kT, + false, + sRated, + cosPhiRated) // Load final LoadInput loadInput = new LoadInput( UUID.fromString("eaf77f7e-9001-479f-94ca-7fb657766f5f"), "test_loadInput", - SystemParticipantTestData.operator, - SystemParticipantTestData.operationTime, + operator, + operationTime, participantNode, - SystemParticipantTestData.cosPhiFixed, - SystemParticipantTestData.standardLoadProfile, + cosPhiFixed, + standardLoadProfile, false, - SystemParticipantTestData.eConsAnnual, - SystemParticipantTestData.sRated, - SystemParticipantTestData.cosPhiRated) + eConsAnnual, + sRated, + cosPhiRated) final LoadInput loadInput1 = new LoadInput( UUID.fromString("eaf77f7e-9001-479f-94ca-7fb657766f6f"), "test_loadInput1", - SystemParticipantTestData.operator, - SystemParticipantTestData.operationTime, + operator, + operationTime, participantNode, - SystemParticipantTestData.cosPhiFixed, - SystemParticipantTestData.standardLoadProfile, + cosPhiFixed, + standardLoadProfile, false, - SystemParticipantTestData.eConsAnnual, - SystemParticipantTestData.sRated, - SystemParticipantTestData.cosPhiRated) + eConsAnnual, + sRated, + cosPhiRated) // Storage final StorageInput storageInput = new StorageInput( UUID.fromString("06b58276-8350-40fb-86c0-2414aa4a0452"), "test_storageInput", - SystemParticipantTestData.operator, - SystemParticipantTestData.operationTime, + operator, + operationTime, participantNode, - SystemParticipantTestData.cosPhiFixed, + cosPhiFixed, storageTypeInput) return new SystemParticipants( @@ -132,7 +132,8 @@ class SampleJointGrid extends SystemParticipantTestData { new HashSet<>(Arrays.asList(loadInput, loadInput1)), Collections.singleton(pvInput), Collections.singleton(storageInput), - Collections.emptySet()) + Collections.emptySet(), + Collections.emptySet()) } private static RawGridElements jointSampleRawGridElements() throws ParseException { @@ -155,10 +156,9 @@ class SampleJointGrid extends SystemParticipantTestData { "nodeA", OperatorInput.NO_OPERATOR_ASSIGNED, OperationTime.notLimited(), - Quantities.getQuantity(1, PowerSystemUnits.PU), + Quantities.getQuantity(1, PU), false, - (Point) - geoJsonReader.read( + (Point) geoJsonReader.read( "{ \"type\": \"Point\", \"coordinates\": [6.592276813887139, 49.37770599548332] }"), GermanVoltageLevelUtils.LV, 1) @@ -169,10 +169,9 @@ class SampleJointGrid extends SystemParticipantTestData { "nodeB", OperatorInput.NO_OPERATOR_ASSIGNED, OperationTime.notLimited(), - Quantities.getQuantity(1, PowerSystemUnits.PU), + Quantities.getQuantity(1, PU), false, - (Point) - geoJsonReader.read( + (Point) geoJsonReader.read( "{ \"type\": \"Point\", \"coordinates\": [6.593358228545043, 49.377139554965595] }"), GermanVoltageLevelUtils.LV, 1) @@ -183,10 +182,9 @@ class SampleJointGrid extends SystemParticipantTestData { "nodeC", OperatorInput.NO_OPERATOR_ASSIGNED, OperationTime.notLimited(), - Quantities.getQuantity(1, PowerSystemUnits.PU), + Quantities.getQuantity(1, PU), false, - (Point) - geoJsonReader.read( + (Point) geoJsonReader.read( "{ \"type\": \"Point\", \"coordinates\": [6.592850044965246, 49.37684839141148] }"), GermanVoltageLevelUtils.LV, 1) @@ -195,11 +193,11 @@ class SampleJointGrid extends SystemParticipantTestData { new LineTypeInput( UUID.fromString("3bed3eb3-9790-4874-89b5-a5434d408088"), "lineType_AtoB", - Quantities.getQuantity(191.636993408203, PowerSystemUnits.SIEMENS_PER_KILOMETRE), - Quantities.getQuantity(0, PowerSystemUnits.SIEMENS_PER_KILOMETRE), - Quantities.getQuantity(0.253899991512299, PowerSystemUnits.OHM_PER_KILOMETRE), - Quantities.getQuantity(0.0691149979829788, PowerSystemUnits.OHM_PER_KILOMETRE), - Quantities.getQuantity(265, PowerSystemUnits.AMPERE), + Quantities.getQuantity(191.636993408203, SIEMENS_PER_KILOMETRE), + Quantities.getQuantity(0, SIEMENS_PER_KILOMETRE), + Quantities.getQuantity(0.253899991512299, OHM_PER_KILOMETRE), + Quantities.getQuantity(0.0691149979829788, OHM_PER_KILOMETRE), + Quantities.getQuantity(265, AMPERE), Quantities.getQuantity(0.4, KILOVOLT)) public static final LineInput lineAB = @@ -253,8 +251,7 @@ class SampleJointGrid extends SystemParticipantTestData { OperationTime.notLimited(), Quantities.getQuantity(1, PowerSystemUnits.PU), false, - (Point) - geoJsonReader.read( + (Point) geoJsonReader.read( "{ \"type\": \"Point\", \"coordinates\": [6.592276813887139, 49.37770599548332] }"), GermanVoltageLevelUtils.MV_10KV, 2) @@ -265,10 +262,9 @@ class SampleJointGrid extends SystemParticipantTestData { "nodeE", OperatorInput.NO_OPERATOR_ASSIGNED, OperationTime.notLimited(), - Quantities.getQuantity(1, PowerSystemUnits.PU), + Quantities.getQuantity(1, PU), false, - (Point) - geoJsonReader.read( + (Point) geoJsonReader.read( "{ \"type\": \"Point\", \"coordinates\": [6.572286813887139, 49.39770699548332] }"), GermanVoltageLevelUtils.MV_10KV, 2) @@ -279,10 +275,9 @@ class SampleJointGrid extends SystemParticipantTestData { "nodeF", OperatorInput.NO_OPERATOR_ASSIGNED, OperationTime.notLimited(), - Quantities.getQuantity(1, PowerSystemUnits.PU), + Quantities.getQuantity(1, PU), false, - (Point) - geoJsonReader.read( + (Point) geoJsonReader.read( "{ \"type\": \"Point\", \"coordinates\": [6.572286813887139, 49.38770799548332] }"), GermanVoltageLevelUtils.MV_10KV, 2) @@ -294,10 +289,9 @@ class SampleJointGrid extends SystemParticipantTestData { "nodeG", OperatorInput.NO_OPERATOR_ASSIGNED, OperationTime.notLimited(), - Quantities.getQuantity(1, PowerSystemUnits.PU), + Quantities.getQuantity(1, PU), false, - (Point) - geoJsonReader.read( + (Point) geoJsonReader.read( "{ \"type\": \"Point\", \"coordinates\": [6.592276813887139, 49.37770599548332] }"), GermanVoltageLevelUtils.HV, 4) @@ -306,11 +300,11 @@ class SampleJointGrid extends SystemParticipantTestData { new LineTypeInput( UUID.fromString("4bed3eb3-9790-4874-89b5-a5434d408088"), "lineType_AtoB", - Quantities.getQuantity(191.636993408203, PowerSystemUnits.SIEMENS_PER_KILOMETRE), - Quantities.getQuantity(0, PowerSystemUnits.SIEMENS_PER_KILOMETRE), - Quantities.getQuantity(0.207000002264977, PowerSystemUnits.OHM_PER_KILOMETRE), - Quantities.getQuantity(0.0691149979829788, PowerSystemUnits.OHM_PER_KILOMETRE), - Quantities.getQuantity(300, PowerSystemUnits.AMPERE), + Quantities.getQuantity(191.636993408203, SIEMENS_PER_KILOMETRE), + Quantities.getQuantity(0, SIEMENS_PER_KILOMETRE), + Quantities.getQuantity(0.207000002264977, OHM_PER_KILOMETRE), + Quantities.getQuantity(0.0691149979829788, OHM_PER_KILOMETRE), + Quantities.getQuantity(300, AMPERE), Quantities.getQuantity(10, KILOVOLT)) public static final LineInput lineDE = diff --git a/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy b/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy index 6066ea93e..7a9717046 100644 --- a/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/SystemParticipantTestData.groovy @@ -5,11 +5,10 @@ */ package edu.ie3.test.common -import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile import edu.ie3.datamodel.models.OperationTime -import edu.ie3.datamodel.models.profile.StandardLoadProfile import edu.ie3.datamodel.models.input.NodeInput import edu.ie3.datamodel.models.input.OperatorInput +import edu.ie3.datamodel.models.input.container.SystemParticipants import edu.ie3.datamodel.models.input.system.* import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed import edu.ie3.datamodel.models.input.system.characteristic.CosPhiP @@ -21,6 +20,8 @@ import edu.ie3.datamodel.models.input.system.type.evcslocation.EvcsLocationType import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput import edu.ie3.datamodel.models.input.thermal.ThermalStorageInput +import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile +import edu.ie3.datamodel.models.profile.StandardLoadProfile import edu.ie3.util.TimeUtil import edu.ie3.util.quantities.interfaces.* import tech.units.indriya.ComparableQuantity @@ -30,30 +31,29 @@ import javax.measure.quantity.* import static edu.ie3.datamodel.models.StandardUnits.* - class SystemParticipantTestData { // general participant data - private static final OperationTime operationTime = OperationTime.builder() + static final OperationTime operationTime = OperationTime.builder() .withStart(TimeUtil.withDefaults.toZonedDateTime("2020-03-24 15:11:31")) .withEnd(TimeUtil.withDefaults.toZonedDateTime("2020-03-25 15:11:31")).build() - private static final OperatorInput operator = new OperatorInput( + static final OperatorInput operator = new OperatorInput( UUID.fromString("8f9682df-0744-4b58-a122-f0dc730f6510"), "TestOperator") - private static final NodeInput participantNode = GridTestData.nodeA + public static final NodeInput participantNode = GridTestData.nodeA // general type data - private static final CosPhiFixed cosPhiFixed = new CosPhiFixed("cosPhiFixed:{(0.0,0.95)}") + static final CosPhiFixed cosPhiFixed = new CosPhiFixed("cosPhiFixed:{(0.0,0.95)}") private static final CosPhiP cosPhiP = new CosPhiP("cosPhiP:{(0.0,1.0),(0.9,1.0),(1.2,-0.3)}") private static final QV qV = new QV("qV:{(0.9,-0.3),(0.95,0.0),(1.05,0.0),(1.1,0.3)}") public static final String cosPhiFixedDeSerialized = "cosPhiFixed:{(0.00,0.95)}" public static final String cosPhiPDeSerialized = "cosPhiP:{(0.00,1.00),(0.90,1.00),(1.20,-0.30)}" public static final String qVDeSerialized = "qV:{(0.90,-0.30),(0.95,0.00),(1.05,0.00),(1.10,0.30)}" - private static final ComparableQuantity sRated = Quantities.getQuantity(25d, ACTIVE_POWER_IN) - private static final double cosPhiRated = 0.95 + static final ComparableQuantity sRated = Quantities.getQuantity(25d, ACTIVE_POWER_IN) + static final double cosPhiRated = 0.95 private static final UUID typeUuid = UUID.fromString("5ebd8f7e-dedb-4017-bb86-6373c4b68eb8") private static final ComparableQuantity capex = Quantities.getQuantity(100d, CAPEX) private static final ComparableQuantity opex = Quantities.getQuantity(50d, ENERGY_PRICE) - private static final ComparableQuantity etaConv = Quantities.getQuantity(98d, EFFICIENCY) + static final ComparableQuantity etaConv = Quantities.getQuantity(98d, EFFICIENCY) // FixedFeedInput @@ -69,11 +69,11 @@ class SystemParticipantTestData { ) // PV - private static final double albedo = 0.20000000298023224d - private static final ComparableQuantity azimuth = Quantities.getQuantity(-8.926613807678223d, AZIMUTH) - private static final ComparableQuantity elevationAngle = Quantities.getQuantity(41.01871871948242d, SOLAR_ELEVATION_ANGLE) - private static double kT = 1d - private static double kG = 0.8999999761581421d + static final double albedo = 0.20000000298023224d + static final ComparableQuantity azimuth = Quantities.getQuantity(-8.926613807678223d, AZIMUTH) + static final ComparableQuantity elevationAngle = Quantities.getQuantity(41.01871871948242d, SOLAR_ELEVATION_ANGLE) + static double kT = 1d + static double kG = 0.8999999761581421d public static final PvInput pvInput = new PvInput( UUID.fromString("d56f15b7-8293-4b98-b5bd-58f6273ce229"), "test_pvInput", @@ -225,8 +225,8 @@ class SystemParticipantTestData { ) // Load - private static final ComparableQuantity eConsAnnual = Quantities.getQuantity(4000, ENERGY_IN) - private static final StandardLoadProfile standardLoadProfile = BdewStandardLoadProfile.H0 + protected static final ComparableQuantity eConsAnnual = Quantities.getQuantity(4000, ENERGY_IN) + protected static final StandardLoadProfile standardLoadProfile = BdewStandardLoadProfile.H0 public static final LoadInput loadInput = new LoadInput( UUID.fromString("eaf77f7e-9001-479f-94ca-7fb657766f5f"), "test_loadInput", @@ -310,6 +310,20 @@ class SystemParticipantTestData { EvcsLocationType.HOME ) + // Energy Management + public static final UUID[] connectedAssets = new UUID[]{loadInput.getUuid(), pvInput.getUuid()} + public static final String emControlStrategy = "self_optimization" + public static final emInput = new EmInput( + UUID.fromString("977157f4-25e5-4c72-bf34-440edc778792"), + "test_emInput", + operator, + operationTime, + participantNode, + cosPhiFixed, + connectedAssets, + emControlStrategy + ) + public static allParticipants = [ fixedFeedInInput, pvInput, @@ -319,7 +333,23 @@ class SystemParticipantTestData { wecInput, evInput, chpInput, - hpInput + hpInput, + emInput ] + static SystemParticipants getEmptySystemParticipants() { + return new SystemParticipants( + [] as Set, + [] as Set, + [] as Set, + [] as Set, + [] as Set, + [] as Set, + [] as Set, + [] as Set, + [] as Set, + [] as Set, + [] as Set) + } + } diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/em_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/em_input.csv new file mode 100644 index 000000000..ad93c0222 --- /dev/null +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/em_input.csv @@ -0,0 +1,2 @@ +uuid,connected_assets,control_strategy,id,node,operates_from,operates_until,operator,q_characteristics +977157f4-25e5-4c72-bf34-440edc778792,eaf77f7e-9001-479f-94ca-7fb657766f5f d56f15b7-8293-4b98-b5bd-58f6273ce229,self_optimization,test_emInput,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z[UTC],2020-03-25T15:11:31Z[UTC],8f9682df-0744-4b58-a122-f0dc730f6510,cosPhiFixed:{(0.00,0.95)}