Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merging view : variant manager implementation #1091

Merged
merged 5 commits into from
Jan 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* Copyright (c) 2019, 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/.
*/
package com.powsybl.iidm.mergingview;

import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.VariantManager;
import com.powsybl.iidm.network.VariantManagerConstants;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

/**
* @author Thomas Adam <tadam at silicom.fr>
*/
class MergingVariantManager implements VariantManager {

private final MergingViewIndex index;

private boolean allowVariantMultiThreadAccess = false;

private String workingVariantId = VariantManagerConstants.INITIAL_VARIANT_ID;

MergingVariantManager(final MergingViewIndex index) {
this.index = Objects.requireNonNull(index, "merging view index is null");
}

private Stream<VariantManager> getVariantManagerStream() {
return index.getNetworkStream().map(Network::getVariantManager);
}

@Override
public Collection<String> getVariantIds() {
final VariantManager vm = getVariantManagerStream().findFirst().orElseThrow(() -> new PowsyblException("No VariantManager found"));
return vm.getVariantIds();
}

@Override
public String getWorkingVariantId() {
return workingVariantId;
}

@Override
public void setWorkingVariant(String variantId) {
this.workingVariantId = variantId;
getVariantManagerStream().forEach(v -> v.setWorkingVariant(variantId));
}

@Override
public void allowVariantMultiThreadAccess(boolean allow) {
this.allowVariantMultiThreadAccess = allow;
getVariantManagerStream().forEach(v -> v.allowVariantMultiThreadAccess(allow));
}

@Override
public boolean isVariantMultiThreadAccessAllowed() {
return allowVariantMultiThreadAccess;
}

// -------------------------------
// Simple delegated methods ------
// -------------------------------
@Override
public void cloneVariant(String sourceVariantId, List<String> targetVariantIds) {
cloneVariant(sourceVariantId, targetVariantIds, false);
}

@Override
public void cloneVariant(String sourceVariantId, List<String> targetVariantIds, boolean mayOverwrite) {
getVariantManagerStream().forEach(v -> v.cloneVariant(sourceVariantId, targetVariantIds, mayOverwrite));
}

@Override
public void cloneVariant(String sourceVariantId, String targetVariantId) {
cloneVariant(sourceVariantId, targetVariantId, false);
}

@Override
public void cloneVariant(String sourceVariantId, String targetVariantId, boolean mayOverwrite) {
getVariantManagerStream().forEach(v -> v.cloneVariant(sourceVariantId, targetVariantId, mayOverwrite));
}

@Override
public void removeVariant(String variantId) {
getVariantManagerStream().forEach(v -> v.removeVariant(variantId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* @author Thomas Adam <tadam at silicom.fr>
*/
public final class MergingView implements Network {
public static final PowsyblException NOT_IMPLEMENTED_EXCEPTION = new PowsyblException("Not implemented exception");
static final PowsyblException NOT_IMPLEMENTED_EXCEPTION = new PowsyblException("Not implemented exception");

private static final Logger LOGGER = LoggerFactory.getLogger(MergingView.class);

Expand Down Expand Up @@ -137,11 +137,15 @@ public Collection<Component> getConnectedComponents() {

private final BusViewAdapter busView;

/** Variant management for all merged networks */
private final MergingVariantManager variantManager;

/** Constructor */
private MergingView(final NetworkFactory factory, final String id, final String format) {
Objects.requireNonNull(factory, "factory is null");

index = new MergingViewIndex(this);
variantManager = new MergingVariantManager(index);
busBreakerView = new BusBreakerViewAdapter(index);
busView = new BusViewAdapter(index);
// Working network will store view informations
Expand Down Expand Up @@ -831,15 +835,14 @@ public <E extends Extension<Network>> Collection<E> getExtensions() {
return workingNetwork.getExtensions();
}

// -------------------------------
// Not implemented methods -------
// -------------------------------

@Override
public VariantManager getVariantManager() {
throw NOT_IMPLEMENTED_EXCEPTION;
return variantManager;
}

// -------------------------------
// Not implemented methods -------
// -------------------------------
@Override
public LineAdder newLine() {
throw NOT_IMPLEMENTED_EXCEPTION;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ public void testSetterGetter() {
assertTrue(mergingView.getExtensions().isEmpty());

// Not implemented yet !
TestUtil.notImplemented(mergingView::getVariantManager);
// Lines
TestUtil.notImplemented(mergingView::newLine);
TestUtil.notImplemented(mergingView::newTieLine);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/**
* Copyright (c) 2019, 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/.
*/
package com.powsybl.iidm.mergingview;

import com.google.common.collect.Iterables;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;

/**
*
* @author Thomas Adam <tadam at silicom.fr>
*/
public class MultiVariantMergingViewTest {

@Test
public void singleThreadTest() {
final MergingView mergingView = MergingView.create("SingleThreadTest", "iidm");
mergingView.merge(EurostagTutorialExample1Factory.create());
final VariantManager manager = mergingView.getVariantManager();
manager.cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, "SecondVariant");
manager.setWorkingVariant("SecondVariant");
final Generator generator = mergingView.getGenerator("GEN");
generator.setVoltageRegulatorOn(false);
assertFalse(generator.isVoltageRegulatorOn());
manager.setWorkingVariant(VariantManagerConstants.INITIAL_VARIANT_ID);
assertTrue(generator.isVoltageRegulatorOn());

assertEquals(2, manager.getVariantIds().size());
manager.removeVariant("SecondVariant");
assertEquals(1, manager.getVariantIds().size());

final List<String> variantsToAdd = Arrays.asList("s1", "s2", "s3", "s4");
manager.cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, variantsToAdd);
assertEquals(variantsToAdd.size() + 1, manager.getVariantIds().size());
}

@Test
public void multiThreadTest() throws InterruptedException {
final MergingView mergingView = MergingView.create("MultiThreadTest", "iidm");
mergingView.merge(EurostagTutorialExample1Factory.create());
final VariantManager manager = mergingView.getVariantManager();
manager.allowVariantMultiThreadAccess(true);
assertTrue(manager.isVariantMultiThreadAccessAllowed());

manager.cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, "SecondVariant");

final Generator generator = mergingView.getGenerator("GEN");

manager.setWorkingVariant(VariantManagerConstants.INITIAL_VARIANT_ID);
generator.setVoltageRegulatorOn(true);

manager.setWorkingVariant("SecondVariant");
generator.setVoltageRegulatorOn(false);

final boolean[] voltageRegulatorOnInitialVariant = new boolean[1];
final boolean[] voltageRegulatorOnSecondVariant = new boolean[1];
final CountDownLatch latch = new CountDownLatch(2); // to sync threads after having set the working variant
ExecutorService service = Executors.newFixedThreadPool(2);
service.invokeAll(Arrays.asList(
() -> {
manager.setWorkingVariant(VariantManagerConstants.INITIAL_VARIANT_ID);
latch.countDown();
latch.await();
voltageRegulatorOnInitialVariant[0] = generator.isVoltageRegulatorOn();
return null;
},
() -> {
manager.setWorkingVariant("SecondVariant");
latch.countDown();
latch.await();
voltageRegulatorOnSecondVariant[0] = generator.isVoltageRegulatorOn();
return null;
})
);
service.shutdown();
service.awaitTermination(1, TimeUnit.MINUTES);
assertTrue(voltageRegulatorOnInitialVariant[0]);
assertFalse(voltageRegulatorOnSecondVariant[0]);
}

@Test
public void multiVariantTopologyTest() throws InterruptedException {
final MergingView mergingView = MergingView.create("MultiVariantTopologyTest", "iidm");
mergingView.merge(EurostagTutorialExample1Factory.create());
final VariantManager manager = mergingView.getVariantManager();
manager.cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, "NEW_VARIANT");
VoltageLevel vlload = mergingView.getVoltageLevel("VLLOAD");
Bus nload = vlload.getBusBreakerView().getBus("NLOAD");
Load newLoad = vlload.newLoad()
.setId("NEW_LOAD")
.setP0(10)
.setQ0(10)
.setBus("NLOAD")
.setConnectableBus("NLOAD")
.add();
manager.setWorkingVariant("NEW_VARIANT");
assertNotNull(newLoad.getTerminal().getBusBreakerView().getBus());
assertEquals(2, Iterables.size(nload.getLoads()));
newLoad.getTerminal().disconnect();
assertNull(newLoad.getTerminal().getBusBreakerView().getBus());
assertEquals(2, Iterables.size(vlload.getLoads()));
assertEquals(1, Iterables.size(nload.getLoads()));
manager.setWorkingVariant(VariantManagerConstants.INITIAL_VARIANT_ID);
assertNotNull(newLoad.getTerminal().getBusBreakerView().getBus());
assertEquals(2, Iterables.size(vlload.getLoads()));
assertEquals(2, Iterables.size(nload.getLoads()));
}

@Test
public void variantNotSetTest() throws InterruptedException {
final MergingView mergingView = MergingView.create("VariantNotSetTest", "iidm");
mergingView.merge(EurostagTutorialExample1Factory.create());
final VariantManager manager = mergingView.getVariantManager();
manager.allowVariantMultiThreadAccess(true);
assertEquals(VariantManagerConstants.INITIAL_VARIANT_ID, manager.getWorkingVariantId());
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(() -> {
try {
mergingView.getGenerator("GEN").getTargetP();
fail();
} catch (Exception ignored) {
}
});
service.shutdown();
service.awaitTermination(1, TimeUnit.MINUTES);
}

@Test
public void variantSetTest() throws InterruptedException {
final MergingView mergingView = MergingView.create("VariantNotSetTest", "iidm");
mergingView.merge(EurostagTutorialExample1Factory.create());
final VariantManager manager = mergingView.getVariantManager();
manager.allowVariantMultiThreadAccess(true);
assertEquals(VariantManagerConstants.INITIAL_VARIANT_ID, manager.getWorkingVariantId());
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(() -> {
try {
manager.setWorkingVariant(VariantManagerConstants.INITIAL_VARIANT_ID);
mergingView.getGenerator("GEN").getTargetP();
} catch (Exception e) {
fail();
}
});
service.shutdown();
service.awaitTermination(1, TimeUnit.MINUTES);
}
}