MetrixVariantsWriterTest.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.integration;
import com.google.common.collect.Range;
import com.google.common.collect.Sets;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.LoadDetail;
import com.powsybl.iidm.network.extensions.LoadDetailAdder;
import com.powsybl.iidm.network.impl.VariantManagerHolder;
import com.powsybl.iidm.network.impl.VariantManagerImpl;
import com.powsybl.iidm.network.impl.extensions.LoadDetailAdderImpl;
import com.powsybl.metrix.mapping.EquipmentVariable;
import com.powsybl.timeseries.RegularTimeSeriesIndex;
import com.powsybl.timeseries.TimeSeriesIndex;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.threeten.extra.Interval;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.Duration;
import java.util.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Paul Bui-Quang {@literal <paul.buiquang at rte-france.com>}
*/
class MetrixVariantsWriterTest {
@Test
void baseCaseTest() throws IOException {
StringWriter writer = new StringWriter();
try (BufferedWriter bufferedWriter = new BufferedWriter(writer)) {
new MetrixVariantsWriter(null, null)
.write(null, bufferedWriter, null);
}
assertEquals(String.join(System.lineSeparator(),
"NT;1;",
"0;") + System.lineSeparator(),
writer.toString());
}
@Test
void variantsTest() throws IOException {
TimeSeriesIndex index = RegularTimeSeriesIndex.create(
Interval.parse("2015-01-01T00:00:00Z/2015-01-01T01:00:00Z"),
Duration.ofMinutes(15));
StringWriter writer = new StringWriter();
MetrixNetwork network = Mockito.mock(MetrixNetwork.class);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l1")).thenReturn(2);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l2")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l3")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l4")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l5")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l6")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l7")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l8")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l9")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l10")).thenReturn(1);
Mockito.when(network.getIndex(MetrixSubset.LOAD, "l13")).thenThrow(new IllegalStateException());
try (BufferedWriter bufferedWriter = new BufferedWriter(writer)) {
new MetrixVariantsWriter(new MetrixVariantProvider() {
@Override
public Range<Integer> getVariantRange() {
return Range.closed(0, 3);
}
@Override
public TimeSeriesIndex getIndex() {
return index;
}
public Set<String> getMappedBreakers() {
return Sets.newHashSet("sw1", "sw2", "sw3");
}
private Generator createGenerator(String id, double targetP) {
Generator g = Mockito.mock(Generator.class);
Mockito.when(g.getId()).thenReturn(id);
Terminal t = Mockito.mock(Terminal.class);
Mockito.when(g.getTerminal()).thenReturn(t);
Mockito.when(t.isConnected()).thenReturn(true);
Mockito.when(g.getTargetP()).thenReturn(targetP);
return g;
}
Map<String, LoadDetail> loadDetailMap = new HashMap<>();
private Load createLoad(String id, double p0, String busId, LoadDetail detail) {
loadDetailMap.put(id, detail);
AbstractNetworkImplTest underlyingNetwork = Mockito.mock(AbstractNetworkImplTest.class);
Mockito.when(underlyingNetwork.getVariantIndex()).thenReturn(0);
Mockito.when(underlyingNetwork.getVariantManager()).thenReturn(Mockito.mock(VariantManagerImpl.class));
Mockito.when(underlyingNetwork.getVariantManager().getVariantArraySize()).thenReturn(1);
Load l = Mockito.mock(Load.class);
Mockito.when(l.getNetwork()).thenReturn(underlyingNetwork);
Mockito.when(l.getId()).thenReturn(id);
Mockito.when(l.getP0()).thenReturn(p0);
Terminal t = Mockito.mock(Terminal.class);
Mockito.when(l.getTerminal()).thenReturn(t);
Terminal.BusBreakerView view = Mockito.mock(Terminal.BusBreakerView.class);
Mockito.when(t.getBusBreakerView()).thenReturn(view);
Bus b = Mockito.mock(Bus.class);
Mockito.when(view.getBus()).thenReturn(b);
if (busId.isEmpty()) {
Mockito.when(b.getId()).thenReturn(id + "_bus");
} else {
Mockito.when(b.getId()).thenReturn(busId);
}
Mockito.when(b.getLoads()).thenReturn(Collections.singletonList(l));
Mockito.when(l.getExtension(LoadDetail.class)).thenAnswer(invocationOnMock -> loadDetailMap.get(id));
Mockito.when(l.newExtension(LoadDetailAdder.class)).thenReturn(new LoadDetailAdderImpl(l));
Mockito.doAnswer(invocationOnMock -> loadDetailMap.put(id, (LoadDetail) invocationOnMock.getArguments()[1]))
.when(l).addExtension(Mockito.any(), Mockito.any());
return l;
}
private LoadDetail createLoadDetail(double fixedActivePower, double variableActivePower) {
LoadDetail l = Mockito.mock(LoadDetail.class);
Mockito.when(l.getFixedActivePower()).thenReturn(fixedActivePower);
Mockito.when(l.getVariableActivePower()).thenReturn(variableActivePower);
return l;
}
private List<Load> createLoads(List<String> idList, List<Float> p0List, String busId, List<LoadDetail> detailList) {
List<Load> loadList = new ArrayList<Load>();
for (int i = 0; i < idList.size(); i++) {
Load l = createLoad(idList.get(i), p0List.get(i), busId, detailList == null ? null : detailList.get(i));
loadList.add(l);
}
Bus b = loadList.get(0).getTerminal().getBusBreakerView().getBus();
Mockito.when(b.getLoads()).thenReturn(loadList);
return loadList;
}
private HvdcLine createHvdcLine(String id, double activePowerSetpoint) {
HvdcLine l = Mockito.mock(HvdcLine.class);
Mockito.when(l.getId()).thenReturn(id);
Mockito.when(l.getActivePowerSetpoint()).thenReturn(activePowerSetpoint);
return l;
}
private TwoWindingsTransformer createPst(String id, double currentTap) {
TwoWindingsTransformer twc = Mockito.mock(TwoWindingsTransformer.class);
Mockito.when(twc.getId()).thenReturn(id);
Terminal t1 = Mockito.mock(Terminal.class);
Mockito.when(twc.getTerminal1()).thenReturn(t1);
Terminal t2 = Mockito.mock(Terminal.class);
Mockito.when(twc.getTerminal1()).thenReturn(t2);
Mockito.when(t1.isConnected()).thenReturn(true);
Mockito.when(t2.isConnected()).thenReturn(true);
PhaseTapChanger pst = Mockito.mock(PhaseTapChanger.class);
Mockito.when(twc.getPhaseTapChanger()).thenReturn(pst);
Mockito.when(pst.getTapPosition()).thenReturn((int) currentTap);
return twc;
}
private Line createLine(String id) {
Line l = Mockito.mock(Line.class);
Mockito.when(l.getId()).thenReturn(id);
return l;
}
private Terminal createTerminal(boolean isConnected) {
Terminal t = Mockito.mock(Terminal.class);
Mockito.when(t.isConnected()).thenReturn(isConnected);
return t;
}
private Switch createSwitch(String id) {
Switch s = Mockito.mock(Switch.class);
Mockito.when(s.getId()).thenReturn(id);
Mockito.when(s.getKind()).thenReturn(SwitchKind.BREAKER);
Mockito.when(s.isRetained()).thenReturn(true);
Mockito.when(s.isOpen()).thenReturn(false);
return s;
}
@Override
public void readVariants(Range<Integer> variantReadRange, MetrixVariantReader reader, Path workingDir) {
Generator g1 = createGenerator("g1", 100f);
Load l1 = createLoad("l1", 10f, "", null);
Load l2 = createLoad("l2", 15f, "", null);
Load l3 = createLoad("l3", 7f, "", null);
Load l4 = createLoad("l4", 10f, "", null);
Load l5 = createLoad("l5", 16f, "", null);
LoadDetail l6d = createLoadDetail(3d, 12d);
Load l6 = createLoad("l6", 15f, "", l6d);
LoadDetail l7d = createLoadDetail(3d, 12d);
Load l7 = createLoad("l7", 18f, "", l7d);
LoadDetail l8d = createLoadDetail(3d, 12d);
Load l8 = createLoad("l8", 19f, "", l8d);
LoadDetail l9d = createLoadDetail(3d, 10d);
Load l9 = createLoad("l9", 15f, "", l9d);
LoadDetail l10d = createLoadDetail(3d, 12d);
Load l10 = createLoad("l10", 15f, "", l10d);
List<Load> loadList = createLoads(Arrays.asList("l11", "l12"), Arrays.asList(12f, 18f), "l1", null);
Load l11 = loadList.get(0);
Load l12 = loadList.get(1);
Load l13 = createLoad("l13", 0f, "", null);
HvdcLine hl1 = createHvdcLine("hl1", 200f);
TwoWindingsTransformer pst1 = createPst("pst1", 17f);
Line line1 = createLine("line1");
Line line2 = createLine("line2");
Terminal terminal1 = createTerminal(true);
Line line3 = createLine("line2");
Terminal terminal2 = createTerminal(false);
Switch sw1 = createSwitch("sw1");
Switch sw2 = createSwitch("sw2");
Switch sw3 = createSwitch("sw3");
Mockito.when(network.getMappedBranch(sw1)).thenReturn(Optional.of("sw1"));
Mockito.when(network.getMappedBranch(sw2)).thenReturn(Optional.of("line1"));
Mockito.when(network.getMappedBranch(sw3)).thenReturn(Optional.of("hl1"));
Mockito.when(line2.getTerminal1()).thenReturn(terminal1);
Mockito.when(line3.getTerminal1()).thenReturn(terminal2);
for (int i = variantReadRange.lowerEndpoint(); i < variantReadRange.upperEndpoint(); i++) {
reader.onVariantStart(i);
// Generator
reader.onEquipmentVariant(g1, EquipmentVariable.TARGET_P, 100.01f + i);
reader.onEquipmentVariant(g1, EquipmentVariable.MIN_P, 111f + i);
reader.onEquipmentVariant(g1, EquipmentVariable.MAX_P, 121f + i);
reader.onEquipmentVariant(g1, EquipmentVariable.DISCONNECTED, (i + 1) % 2);
// Load without LoadDetail
reader.onEquipmentVariant(l1, EquipmentVariable.P0, 10f + i);
reader.onEquipmentVariant(l2, EquipmentVariable.P0, 16f + i); // CONELE = 16 + i
reader.onEquipmentVariant(l3, EquipmentVariable.FIXED_ACTIVE_POWER, 6f + i); // CONELE = 6 + i
reader.onEquipmentVariant(l4, EquipmentVariable.VARIABLE_ACTIVE_POWER, 8f + i); // CONELE = 8 + i
reader.onEquipmentVariant(l5, EquipmentVariable.FIXED_ACTIVE_POWER, 6f + i);
reader.onEquipmentVariant(l5, EquipmentVariable.VARIABLE_ACTIVE_POWER, 8f + i); // CONELE = 14 + 2*i
reader.onEquipmentVariant(l6, EquipmentVariable.FIXED_ACTIVE_POWER, 5f + i);
reader.onEquipmentVariant(l6, EquipmentVariable.VARIABLE_ACTIVE_POWER, 10f - i); // not present cause identical to base case
// Load with LoadDetail
reader.onEquipmentVariant(l7, EquipmentVariable.P0, 17f + i); // CONELE = 17 + i
reader.onEquipmentVariant(l8, EquipmentVariable.FIXED_ACTIVE_POWER, 6f + i); // CONELE = 6 + i + 12
reader.onEquipmentVariant(l9, EquipmentVariable.VARIABLE_ACTIVE_POWER, 8f + i); // CONELE = 3 + 8 + i
reader.onEquipmentVariant(l10, EquipmentVariable.FIXED_ACTIVE_POWER, 6f + i);
reader.onEquipmentVariant(l10, EquipmentVariable.VARIABLE_ACTIVE_POWER, 8f + i); // CONELE = 14 + 2*i
// Loads on a same Bus
reader.onEquipmentVariant(l11, EquipmentVariable.P0, 10f + i);
reader.onEquipmentVariant(l12, EquipmentVariable.P0, 20f - i); // not present cause identical to base case
// Hvdc
reader.onEquipmentVariant(hl1, EquipmentVariable.ACTIVE_POWER_SETPOINT, 200.0001f + i);
reader.onEquipmentVariant(hl1, EquipmentVariable.MIN_P, 210f + i);
reader.onEquipmentVariant(hl1, EquipmentVariable.MAX_P, 220f + i);
// Breakers
reader.onEquipmentVariant(sw1, EquipmentVariable.OPEN, (i + 1) % 2);
reader.onEquipmentVariant(sw2, EquipmentVariable.OPEN, i % 2);
reader.onEquipmentVariant(sw3, EquipmentVariable.OPEN, (i + 1) % 2);
// Metrix
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_N, 1001f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_N1, 1011f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_NK, 1021f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_ITAM, 1031f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_ITAM_NK, 1041f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_N_END_OR, 2001f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_N1_END_OR, 2011f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_NK_END_OR, 2021f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_ITAM_END_OR, 2031f + i);
reader.onEquipmentVariant(line1, MetrixVariable.THRESHOLD_ITAM_NK_END_OR, 2041f + i);
reader.onEquipmentVariant(line2, EquipmentVariable.DISCONNECTED, (i + 1) % 2);
reader.onEquipmentVariant(line3, EquipmentVariable.DISCONNECTED, (i + 1) % 2);
reader.onEquipmentVariant(g1, MetrixVariable.OFF_GRID_COST_DOWN, 1111f + i);
reader.onEquipmentVariant(g1, MetrixVariable.OFF_GRID_COST_UP, 1121f + i);
reader.onEquipmentVariant(g1, MetrixVariable.ON_GRID_COST_DOWN, 1131f + i);
reader.onEquipmentVariant(g1, MetrixVariable.ON_GRID_COST_UP, 1141f + i);
// Pst
reader.onEquipmentVariant(pst1, EquipmentVariable.PHASE_TAP_POSITION, 17f + i);
reader.onEquipmentVariant(pst1, EquipmentVariable.DISCONNECTED, (i + 1) % 2);
reader.onEquipmentVariant(l1, MetrixVariable.CURATIVE_COST_DOWN, 10f + i);
// load out of main cc
reader.onEquipmentVariant(l13, MetrixVariable.CURATIVE_COST_DOWN, i);
reader.onVariantEnd(i);
}
reader.onVariantStart(variantReadRange.upperEndpoint());
reader.onVariantEnd(variantReadRange.upperEndpoint());
}
}, network).write(Range.closed(0, 3), bufferedWriter, null);
}
assertEquals(
String.join(System.lineSeparator(), IOUtils.readLines(MetrixVariantsWriterTest.class.getResourceAsStream("/expected/variantsOutput.txt"), StandardCharsets.UTF_8)),
writer.toString().trim()
);
}
abstract static class AbstractNetworkImplTest implements Network, VariantManagerHolder {
}
}