EquipmentGroupTimeSeriesMapperObserverTest.java
/*
* Copyright (c) 2021, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.metrix.mapping;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Range;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.serde.NetworkSerDe;
import com.powsybl.timeseries.*;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.threeten.extra.Interval;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.time.Duration;
import java.util.*;
import static com.powsybl.metrix.mapping.EquipmentGroupTimeSeriesMapperObserver.GROUP;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
/**
* @author Marianne Funfrock {@literal <marianne.funfrock at rte-france.com>}
*/
class EquipmentGroupTimeSeriesMapperObserverTest {
private final int chunkSize = 2;
private final MappingParameters mappingParameters = MappingParameters.load();
private FileSystem fileSystem;
private Network network;
private ReadOnlyTimeSeriesStore store;
private TimeSeriesIndex regularIndex;
@BeforeEach
public void setUp() {
this.fileSystem = Jimfs.newFileSystem(Configuration.unix());
network = NetworkSerDe.read(Objects.requireNonNull(getClass().getResourceAsStream("/simpleNetwork.xml")));
regularIndex = RegularTimeSeriesIndex.create(Interval.parse("2015-01-01T01:00:00Z/2015-01-01T02:00:00Z"), Duration.ofHours(1));
store = new ReadOnlyTimeSeriesStoreCache(
TimeSeries.createDouble("ts_10", regularIndex, 10d, 11d),
TimeSeries.createDouble("ts_20", regularIndex, 20d, 21d)
);
}
@AfterEach
public void tearDown() throws IOException {
this.fileSystem.close();
}
private final String mapToGeneratorsScript =
String.join(System.lineSeparator(),
"mapToGenerators {",
" timeSeriesName 'ts_10'",
" filter { generator.id == 'FSSV.O11_G' }",
"}");
final String provideGroupTsGenerators = String.join(System.lineSeparator(),
"provideGroupTsGenerators {",
" filter { generator.terminal.voltageLevel.id == 'FSSV.O1' }",
" group %s",
"}");
final String provideGroupWithNameTsGenerators = String.join(System.lineSeparator(),
"provideGroupTsGenerators {",
" filter { generator.terminal.voltageLevel.id == 'FSSV.O1' }",
" group VOLTAGE_LEVEL",
" withName 'userGivenName'",
"}");
final String mapToLoadsScript = String.join(System.lineSeparator(),
"mapToLoads {",
" timeSeriesName %s",
" variable %s",
" filter { load.id == %s }",
"}");
final String provideGroupTsLoadsVoltageLevel = String.join(System.lineSeparator(),
"provideGroupTsLoads {",
" filter { load.terminal.voltageLevel.id == 'FVALDI1' }",
" group VOLTAGE_LEVEL",
"}");
final String provideGroupWithNameTsLoadsVoltageLevel = String.join(System.lineSeparator(),
"provideGroupTsLoads {",
" filter { load.terminal.voltageLevel.id == 'FVALDI1' }",
" group VOLTAGE_LEVEL",
" withName 'userGivenName'",
"}");
private TimeSeriesMappingConfig loadMappingConfig(String script) {
return new TimeSeriesDslLoader(script).load(network, mappingParameters, store, new DataTableStore(), null);
}
private void runMapping(TimeSeriesMappingConfig mappingConfig, TimeSeriesMapperObserver observer) {
TimeSeriesMapperParameters parameters = new TimeSeriesMapperParameters(new TreeSet<>(Collections.singleton(1)),
Range.closed(0, 1), true, false, false, mappingParameters.getToleranceThreshold());
TimeSeriesMapper mapper = new TimeSeriesMapper(mappingConfig, parameters, network, new TimeSeriesMappingLogger());
mapper.mapToNetwork(store, ImmutableList.of(observer));
}
private void generatorTest(TimeSeriesMappingConfig mappingConfig, String expectedTimeSeriesName) {
// Create observer
TimeSeriesMapperObserver observer = new EquipmentGroupTimeSeriesMapperObserver(network, mappingConfig, chunkSize, Range.closed(0, chunkSize)) {
@Override
public void addTimeSeries(String timeSeriesName, int version, Range<Integer> pointRange, double[] values, Map<String, String> tags, TimeSeriesIndex index) {
assertThat(timeSeriesName).isEqualTo(expectedTimeSeriesName);
assertThat(version).isEqualTo(1);
assertThat(index).isEqualTo(regularIndex);
assertThat(pointRange).isEqualTo(Range.closed(0, chunkSize - 1));
assertThat(values).isEqualTo(new double[]{10 + 480, 11 + 480});
assertThat(tags).containsEntry("equipment", GROUP);
}
};
// Run mapping
runMapping(mappingConfig, observer);
}
private void checkLoadTest(Set<String> expectedTimeSeriesNames, String timeSeriesName, int version, Range<Integer> pointRange, Map<String, String> tags, TimeSeriesIndex index) {
assertTrue(expectedTimeSeriesNames.contains(timeSeriesName));
assertThat(version).isEqualTo(1);
assertThat(index).isEqualTo(regularIndex);
assertThat(pointRange).isEqualTo(Range.closed(0, chunkSize - 1));
assertThat(tags).containsEntry("equipment", GROUP);
}
private void loadTest(TimeSeriesMappingConfig mappingConfig, double[] expectedVariableActivePowerValues, double[] expectedFixedActivePowerValues) {
// Expected time series names
final String variableActivePowerTimeSeriesName = "FVALDI1_variableActivePower";
final String fixedActivePowerTimeSeriesName = "FVALDI1_fixedActivePower";
final Set<String> expectedTimeSeriesNames = ImmutableSet.of(variableActivePowerTimeSeriesName, fixedActivePowerTimeSeriesName);
// Create observer
TimeSeriesMapperObserver observer = new EquipmentGroupTimeSeriesMapperObserver(network, mappingConfig, chunkSize, Range.closed(0, chunkSize)) {
boolean isVariableActivePowerTimeSeriesOk = false;
boolean isFixedActivePowerTimeSeriesOk = false;
@Override
public void addTimeSeries(String timeSeriesName, int version, Range<Integer> pointRange, double[] values, Map<String, String> tags, TimeSeriesIndex index) {
checkLoadTest(expectedTimeSeriesNames, timeSeriesName, version, pointRange, tags, index);
switch (timeSeriesName) {
case variableActivePowerTimeSeriesName -> {
isVariableActivePowerTimeSeriesOk = true;
assertThat(values).isEqualTo(expectedVariableActivePowerValues);
}
case fixedActivePowerTimeSeriesName -> {
isFixedActivePowerTimeSeriesOk = true;
assertThat(values).isEqualTo(expectedFixedActivePowerValues);
}
default -> fail();
}
}
@Override
public void end() {
// All expected time series are provided
assertThat(isVariableActivePowerTimeSeriesOk).isTrue();
assertThat(isFixedActivePowerTimeSeriesOk).isTrue();
}
};
// Run mapping
runMapping(mappingConfig, observer);
}
/*
* GENERATOR TEST
* 2 generators in FSSV.O1 voltageLevel :
* FSSV.O11_G is mapped
* FSSV.O12_G is not mapped
*/
@Test
void generatorVoltageLevelTest() {
String script = String.join(System.lineSeparator(),
mapToGeneratorsScript,
String.format(provideGroupTsGenerators, "VOLTAGE_LEVEL"));
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
final String expectedTimeSeriesName = "FSSV.O1_" + EquipmentVariable.TARGET_P.getVariableName();
generatorTest(mappingConfig, expectedTimeSeriesName);
}
@Test
void generatorSubstationTest() {
String script = String.join(System.lineSeparator(),
mapToGeneratorsScript,
String.format(provideGroupTsGenerators, "SUBSTATION"));
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
final String expectedTimeSeriesName = "FSSV._" + EquipmentVariable.TARGET_P.getVariableName();
generatorTest(mappingConfig, expectedTimeSeriesName);
}
@Test
void generatorWithNameTest() {
String script = String.join(System.lineSeparator(),
mapToGeneratorsScript,
provideGroupWithNameTsGenerators);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
final String expectedTimeSeriesName = "FSSV.O1_userGivenName_" + EquipmentVariable.TARGET_P.getVariableName();
generatorTest(mappingConfig, expectedTimeSeriesName);
}
/*
* LOAD TEST
* 2 loads in FVALDI1 voltageLevel :
* FVALDI11_L p0 = 470 with LoadDetail extension variableActivePower = 70 fixedActivePower = 400
* FVALDI11_L2 p0 = 10
*/
/*
* FVALDI11_L mapped
* FVALDI11_L2 not mapped
*/
@Test
void loadMapToP0OnLoadWithDetailTest() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "p0", "\"FVALDI11_L\""),
provideGroupTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
loadTest(mappingConfig, new double[]{10 + 10, 11 + 10}, new double[]{0, 0});
}
@Test
void loadMapToVariableActivePowerOnLoadWithDetailTest() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "variableActivePower", "\"FVALDI11_L\""),
provideGroupTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
loadTest(mappingConfig, new double[]{10 + 10, 11 + 10}, new double[]{400, 400});
}
@Test
void loadMapToFixedActivePowerOnLoadWithDetailTest() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "fixedActivePower", "\"FVALDI11_L\""),
provideGroupTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
loadTest(mappingConfig, new double[]{70 + 10, 70 + 10}, new double[]{10, 11});
}
@Test
void loadMapToAllActivePowerOnLoadWithDetailTest() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "variableActivePower", "\"FVALDI11_L\""),
String.format(mapToLoadsScript, "\"ts_20\"", "fixedActivePower", "\"FVALDI11_L\""),
provideGroupTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
loadTest(mappingConfig, new double[]{10 + 10, 11 + 10}, new double[]{20, 21});
}
/*
* LOAD TEST
* FVALDI11_L2 mapped
* FVALDI11_L not mapped
*/
@Test
void loadMapToP0Test() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "p0", "\"FVALDI11_L2\""),
provideGroupTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
loadTest(mappingConfig, new double[]{70 + 10, 70 + 11}, new double[]{400, 400});
}
@Test
void loadMapToVariableActivePowerTest() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "variableActivePower", "\"FVALDI11_L2\""),
provideGroupTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
loadTest(mappingConfig, new double[]{70 + 10, 70 + 11}, new double[]{400, 400});
}
@Test
void loadMapToFixedActivePowerTest() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "fixedActivePower", "\"FVALDI11_L2\""),
provideGroupTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
loadTest(mappingConfig, new double[]{70, 70}, new double[]{400 + 10, 400 + 11});
}
@Test
void loadMapToAllActivePowerTest() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "variableActivePower", "\"FVALDI11_L2\""),
String.format(mapToLoadsScript, "\"ts_20\"", "fixedActivePower", "\"FVALDI11_L2\""),
provideGroupTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
loadTest(mappingConfig, new double[]{70 + 10, 70 + 11}, new double[]{400 + 20, 400 + 21});
}
@Test
void loadMapToP0WithNameTest() {
String script = String.join(System.lineSeparator(),
String.format(mapToLoadsScript, "\"ts_10\"", "p0", "\"FVALDI11_L2\""),
provideGroupWithNameTsLoadsVoltageLevel);
TimeSeriesMappingConfig mappingConfig = loadMappingConfig(script);
Set<String> actualTimeSeriesNames = new HashSet<>();
// Create observer
TimeSeriesMapperObserver observer = new EquipmentGroupTimeSeriesMapperObserver(network, mappingConfig, chunkSize, Range.closed(0, chunkSize)) {
@Override
public void addTimeSeries(String timeSeriesName, int version, Range<Integer> pointRange, double[] values, Map<String, String> tags, TimeSeriesIndex index) {
actualTimeSeriesNames.add(timeSeriesName);
}
};
// Run mapping
runMapping(mappingConfig, observer);
assertThat(actualTimeSeriesNames).hasSize(2);
assertTrue(actualTimeSeriesNames.contains("FVALDI1_userGivenName_variableActivePower"));
assertTrue(actualTimeSeriesNames.contains("FVALDI1_userGivenName_fixedActivePower"));
}
}