Skip to content

Commit

Permalink
Merge branch 'refs/heads/dev' into pp/#1089-enhance-loadinput-by-cate…
Browse files Browse the repository at this point in the history
…gories-for-markov

# Conflicts:
#	CHANGELOG.md
  • Loading branch information
pierrepetersmeier committed Jun 6, 2024
2 parents 305f5ad + d2bca6b commit eb81dfb
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Enhancing `VoltageLevel` with `equals` method [#1063](https://github.com/ie3-institute/PowerSystemDataModel/issues/1063)
- `ConnectorValidationUtils` checks if parallel devices is > 0 [#1077](https://github.com/ie3-institute/PowerSystemDataModel/issues/1077)
- `GridContainerValidationUtils` checks the connectivity for all defined operation time intervals [#1091](https://github.com/ie3-institute/PowerSystemDataModel/issues/1091)
- Enhance LoadInput by categories for markov [#1089](https://github.com/ie3-institute/PowerSystemDataModel/issues/1089)

### Fixed
Expand Down
1 change: 1 addition & 0 deletions docs/readthedocs/io/ValidationUtils.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The methods in ValidationUtils and subclasses can be used to check that objects
The general validation checks:
- if assigned values are valid, e.g. lines are not allowed to have negative lengths or the rated power factor of any unit must be between 0 and 1
- furthermore, several connections are checked, e.g. that lines only connect nodes of the same voltage level or that the voltage levels indicated for the transformer sides match the voltage levels of the nodes they are connected to.
- the connectivity of the given grid for all defined operation intervals

The uniqueness validation checks if a collection of given objects are unique in either:
- a specific field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,33 @@
import static edu.ie3.datamodel.utils.validation.UniquenessValidationUtils.checkAssetUniqueness;
import static edu.ie3.datamodel.utils.validation.UniquenessValidationUtils.checkUniqueEntities;

import edu.ie3.datamodel.exceptions.*;
import edu.ie3.datamodel.exceptions.DuplicateEntitiesException;
import edu.ie3.datamodel.exceptions.InvalidEntityException;
import edu.ie3.datamodel.exceptions.InvalidGridException;
import edu.ie3.datamodel.exceptions.ValidationException;
import edu.ie3.datamodel.models.OperationTime;
import edu.ie3.datamodel.models.input.AssetInput;
import edu.ie3.datamodel.models.input.MeasurementUnitInput;
import edu.ie3.datamodel.models.input.NodeInput;
import edu.ie3.datamodel.models.input.connector.*;
import edu.ie3.datamodel.models.input.connector.ConnectorInput;
import edu.ie3.datamodel.models.input.connector.LineInput;
import edu.ie3.datamodel.models.input.connector.Transformer3WInput;
import edu.ie3.datamodel.models.input.container.*;
import edu.ie3.datamodel.models.input.graphics.GraphicInput;
import edu.ie3.datamodel.models.input.system.SystemParticipantInput;
import edu.ie3.datamodel.utils.ContainerUtils;
import edu.ie3.datamodel.utils.Try;
import edu.ie3.datamodel.utils.Try.*;
import edu.ie3.datamodel.utils.Try.Failure;
import edu.ie3.datamodel.utils.Try.Success;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jgrapht.Graph;
import org.jgrapht.alg.connectivity.ConnectivityInspector;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleGraph;

public class GridContainerValidationUtils extends ValidationUtils {

Expand Down Expand Up @@ -155,9 +169,105 @@ private GridContainerValidationUtils() {
exceptions.add(MeasurementUnitValidationUtils.check(measurement));
});

exceptions.addAll(checkConnectivity(rawGridElements));

return exceptions;
}

/**
* Checks the connectivity of the given grid for all defined {@link OperationTime}s. If every
* {@link AssetInput} is set to {@link OperationTime#notLimited()}, the connectivity is only
* checked once.
*
* @param rawGridElements to check
* @return a try
*/
protected static List<Try<Void, InvalidGridException>> checkConnectivity(
RawGridElements rawGridElements) {
Set<ZonedDateTime> times =
rawGridElements.allEntitiesAsList().stream()
.map(AssetInput::getOperationTime)
.filter(OperationTime::isLimited)
.map(OperationTime::getOperationLimit)
.filter(Optional::isPresent)
.map(Optional::get)
.map(interval -> Set.of(interval.getLower(), interval.getUpper()))
.flatMap(Collection::stream)
.collect(Collectors.toSet());

if (times.isEmpty()) {
return List.of(checkConnectivity(rawGridElements, Optional.empty()));
} else {
return times.stream()
.sorted()
.map(time -> checkConnectivity(rawGridElements, Optional.of(time)))
.toList();
}
}

/**
* Checks if the given {@link RawGridElements} from a connected grid.
*
* @param rawGridElements to check
* @param time for operation filtering
* @return a try
*/
protected static Try<Void, InvalidGridException> checkConnectivity(
RawGridElements rawGridElements, Optional<ZonedDateTime> time) {

Predicate<AssetInput> isInOperation =
assetInput -> time.map(assetInput::inOperationOn).orElse(true);

// build graph
Graph<UUID, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class);

rawGridElements.getNodes().stream()
.filter(isInOperation)
.forEach(node -> graph.addVertex(node.getUuid()));
rawGridElements.getLines().stream()
.filter(isInOperation)
.forEach(
connector ->
graph.addEdge(connector.getNodeA().getUuid(), connector.getNodeB().getUuid()));
rawGridElements.getTransformer2Ws().stream()
.filter(isInOperation)
.forEach(
connector ->
graph.addEdge(connector.getNodeA().getUuid(), connector.getNodeB().getUuid()));
rawGridElements.getTransformer3Ws().stream()
.filter(isInOperation)
.forEach(
connector ->
graph.addEdge(connector.getNodeA().getUuid(), connector.getNodeB().getUuid()));
rawGridElements.getSwitches().stream()
.filter(isInOperation)
.forEach(
connector ->
graph.addEdge(connector.getNodeA().getUuid(), connector.getNodeB().getUuid()));

ConnectivityInspector<UUID, DefaultEdge> inspector = new ConnectivityInspector<>(graph);

if (inspector.isConnected()) {
return Success.empty();
} else {
List<Set<UUID>> sets = inspector.connectedSets();

List<UUID> unconnected =
sets.stream()
.max(Comparator.comparing(Set::size))
.map(set -> graph.vertexSet().stream().filter(v -> !set.contains(v)).toList())
.orElse(List.of());

String message = "The grid contains unconnected elements";

if (time.isPresent()) {
message += " for time " + time.get();
}

return Failure.of(new InvalidGridException(message + ": " + unconnected));
}
}

/**
* Checks the validity of each and every system participant. Moreover, it checks, if the systems
* are connected to a node that is not in the provided set
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* © 2024. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.utils.validation

import edu.ie3.datamodel.exceptions.InvalidGridException
import edu.ie3.datamodel.models.OperationTime
import edu.ie3.datamodel.models.input.container.RawGridElements
import edu.ie3.datamodel.utils.Try
import edu.ie3.test.common.GridTestData as GTD
import spock.lang.Shared
import spock.lang.Specification

import java.time.ZonedDateTime

class GridContainerValidationUtilsTest extends Specification {
@Shared
private ZonedDateTime start

@Shared
private RawGridElements limitedElements

def setupSpec() {
start = ZonedDateTime.now()

def operationTimeFrame1 = OperationTime.builder().withStart(start).withEnd(start.plusHours(2)).build()
def operationTimeFrame2 = OperationTime.builder().withStart(start.plusHours(1)).withEnd(start.plusHours(3)).build()

def nodes = [
GTD.nodeC,
GTD.nodeD,
GTD.nodeE,
GTD.nodeF,
GTD.nodeG
] as Set

def lines = [
GTD.lineCtoD.copy().operationTime(operationTimeFrame1).build(),
GTD.lineFtoG.copy().operationTime(operationTimeFrame2).build()
] as Set

def transformers = [
GTD.transformerCtoF.copy().operationTime(operationTimeFrame1).build(),
GTD.transformerCtoE.copy().operationTime(operationTimeFrame2).build()
] as Set

limitedElements = new RawGridElements(nodes, lines, transformers, [] as Set, [] as Set, [] as Set)
}

def "The GridContainerValidationUtils should check the connectivity for all operation intervals correctly"() {
when:
def actual = GridContainerValidationUtils.checkConnectivity(limitedElements)

then:
actual.size() == 4
actual.get(0).failure
actual.get(1).success
actual.get(2).success
actual.get(3).failure

actual.get(0).exception.get().message == "The grid contains unconnected elements for time " + start + ": " + [
GTD.nodeE.uuid,
GTD.nodeG.uuid
]
actual.get(3).exception.get().message == "The grid contains unconnected elements for time " + start.plusHours(3) + ": " + [
GTD.nodeD.uuid,
GTD.nodeF.uuid,
GTD.nodeG.uuid
]
}

def "The GridContainerValidationUtils should check the connectivity correctly"() {
when:
def actual = GridContainerValidationUtils.checkConnectivity(limitedElements, time as Optional<ZonedDateTime>)

then:
actual == expectedResult

where:
time || expectedResult
Optional.empty() || Try.Success.empty()
Optional.of(start.plusHours(1)) || Try.Success.empty()
}

def "The GridContainerValidationUtils should return an exception if the grid is not properly connected"() {
when:
def actual = GridContainerValidationUtils.checkConnectivity(limitedElements, time as Optional<ZonedDateTime>)

then:
actual.exception.get().message == expectedException.message

where:
time || expectedException
Optional.of(start) || new InvalidGridException("The grid contains unconnected elements for time " + start + ": " + [
GTD.nodeE.uuid,
GTD.nodeG.uuid
])
Optional.of(start.plusHours(3)) || new InvalidGridException("The grid contains unconnected elements for time " + start.plusHours(3) + ": " + [
GTD.nodeD.uuid,
GTD.nodeF.uuid,
GTD.nodeG.uuid
])
}
}

0 comments on commit eb81dfb

Please sign in to comment.