Skip to content

Commit

Permalink
BusVoltagePerTargetV sensitivity factor (#1640)
Browse files Browse the repository at this point in the history
Signed-off-by: Anne Tilloy <[email protected]>

Co-authored-by: yichen88 <[email protected]>
Co-authored-by: Sylvain Leclerc <[email protected]>
  • Loading branch information
3 people authored Apr 1, 2021
1 parent 68407a5 commit dfd1c5c
Show file tree
Hide file tree
Showing 10 changed files with 619 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* 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/.
*/
package com.powsybl.iidm.network;

import java.util.Objects;
import java.util.Optional;

/**
* @author Yichen TANG <yichen.tang at rte-france.com>
*/
public abstract class AbstractBusRef implements BusRef {

@Override
public Optional<Bus> resolve(Network network, TopologyLevel level) {
Objects.requireNonNull(network);
Objects.requireNonNull(level);
if (TopologyLevel.NODE_BREAKER == level) {
throw new IllegalArgumentException(level + " is not supported in resolve a BusRef.");
}
return resolveByLevel(network, level);
}

protected static Optional<Bus> chooseBusByLevel(Terminal t, TopologyLevel level) {
if (level == TopologyLevel.BUS_BRANCH) {
return Optional.ofNullable(t.getBusView().getBus());
} else {
return Optional.ofNullable(t.getBusBreakerView().getBus());
}
}

protected abstract Optional<Bus> resolveByLevel(Network network, TopologyLevel level);
}
26 changes: 26 additions & 0 deletions iidm/iidm-api/src/main/java/com/powsybl/iidm/network/BusRef.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* 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/.
*/
package com.powsybl.iidm.network;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import java.util.Optional;

@JsonSubTypes({
@JsonSubTypes.Type(value = IdBasedBusRef.class)
})
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)
public interface BusRef {

/**
* @return an empty if not found
* @throws com.powsybl.commons.PowsyblException if underlying implementation not supported
* @throws IllegalArgumentException if try to resolve by {@link com.powsybl.iidm.network.TopologyLevel#NODE_BREAKER}
*/
Optional<Bus> resolve(Network network, TopologyLevel level);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* 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/.
*/
package com.powsybl.iidm.network;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.powsybl.commons.PowsyblException;

import java.util.Objects;
import java.util.Optional;

/**
* There would be three types of id:
* 1. id of equipment:
* 2. id of a configured bus itself:
* 3. id of branch, in this case, side is required
* @author Yichen TANG <yichen.tang at rte-france.com>
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class IdBasedBusRef extends AbstractBusRef {

private final String id;
private final Branch.Side side;

public IdBasedBusRef(String id) {
this.id = Objects.requireNonNull(id);
this.side = null;
}

@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public IdBasedBusRef(@JsonProperty("id") String id, @JsonProperty("side") Branch.Side side) {
this.id = Objects.requireNonNull(id);
this.side = side;
}

@Override
protected Optional<Bus> resolveByLevel(Network network, TopologyLevel level) {
if (side == null) {
final Identifiable<?> identifiable = network.getIdentifiable(id);
if (identifiable == null) {
return Optional.empty();
}
if (identifiable instanceof Bus) {
Bus bus = (Bus) identifiable;
if (level == TopologyLevel.BUS_BRANCH) {
return bus.getConnectedTerminalStream().map(t -> t.getBusView().getBus()).filter(Objects::nonNull).findFirst();
} else {
return Optional.of(bus);
}
} else if (identifiable instanceof Injection) {
final Injection injection = (Injection) identifiable;
return chooseBusByLevel(injection.getTerminal(), level);
} else {
throw new PowsyblException(id + " is not a bus or injection.");
}
} else {
Branch branch = network.getBranch(id);
Terminal terminal;
switch (side) {
case ONE:
terminal = branch.getTerminal1();
break;
case TWO:
terminal = branch.getTerminal2();
break;
default:
throw new AssertionError("Unexpected side: " + side);
}
return chooseBusByLevel(terminal, level);
}
}

public String getId() {
return id;
}

public Branch.Side getSide() {
return side;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof IdBasedBusRef)) {
return false;
}

IdBasedBusRef that = (IdBasedBusRef) o;

if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) {
return false;
}
return getSide() != null ? getSide().equals(that.getSide()) : that.getSide() == null;
}

@Override
public int hashCode() {
return Objects.hash(id, side);
}
}
125 changes: 125 additions & 0 deletions iidm/iidm-api/src/test/java/com/powsybl/iidm/network/BusRefTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/**
* 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/.
*/
package com.powsybl.iidm.network;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;

import java.util.Collections;
import java.util.Set;
import java.util.stream.Stream;

import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* @author Yichen TANG <yichen.tang at rte-france.com>
*/
public class BusRefTest {

private final Bus bvBus = mock(Bus.class);
private final Bus bbvBus = mock(Bus.class);

@Test
public void testIdBasedBusRef() throws JsonProcessingException {
Network network = mock(Network.class);
Network.BusView bv = mock(Network.BusView.class);

VoltageLevel vl = mock(VoltageLevel.class);
when(bbvBus.getVoltageLevel()).thenReturn(vl);
when(network.getBusView()).thenReturn(bv);
when(bv.getBus(eq("busId"))).thenReturn(bvBus);

final BusRef busRef = new IdBasedBusRef("busId");
when(network.getIdentifiable(eq("busId"))).thenReturn((Identifiable) bvBus);
when(bvBus.getId()).thenReturn("busId");
Terminal busTerminal = mock(Terminal.class);
Terminal.BusView terBusView = mock(Terminal.BusView.class);
when(busTerminal.getBusView()).thenReturn(terBusView);
when(terBusView.getBus()).thenReturn(bvBus);
final Set<Terminal> singleton = Collections.singleton(busTerminal);
final Stream mock = singleton.stream();
when(bvBus.getConnectedTerminalStream()).thenReturn(mock);
assertEquals(bvBus, busRef.resolve(network, TopologyLevel.BUS_BRANCH).orElseThrow(AssertionError::new));

when(network.getIdentifiable(eq("busId"))).thenReturn((Identifiable) bbvBus);
assertEquals(bbvBus, busRef.resolve(network, TopologyLevel.BUS_BREAKER).orElseThrow(AssertionError::new));

assertFalse(new IdBasedBusRef("another").resolve(network, TopologyLevel.BUS_BRANCH).isPresent());

ObjectMapper objectMapper = new ObjectMapper();
final String json = objectMapper.writeValueAsString(busRef);
assertEquals("{\"@c\":\".IdBasedBusRef\",\"id\":\"busId\"}", json);
final BusRef deserialized = objectMapper.readValue(json, BusRef.class);
assertEquals(busRef, deserialized);

Identifiable busbarSection = mock(BusbarSection.class);
when(network.getIdentifiable(eq("busbarId"))).thenReturn(busbarSection);
final BusbarSection bbs = (BusbarSection) busbarSection;
Terminal terminal = mock(Terminal.class);
when(bbs.getTerminal()).thenReturn(terminal);
Terminal.BusView tbv = mock(Terminal.BusView.class);
when(terminal.getBusView()).thenReturn(tbv);
when(tbv.getBus()).thenReturn(bvBus);
final IdBasedBusRef busbarRef = new IdBasedBusRef("busbarId");
assertEquals(bvBus, busbarRef.resolve(network, TopologyLevel.BUS_BRANCH).orElseThrow(AssertionError::new));

Terminal.BusBreakerView bbv = mock(Terminal.BusBreakerView.class);
when(terminal.getBusBreakerView()).thenReturn(bbv);
when(bbv.getBus()).thenReturn(bbvBus);
assertEquals(bbvBus, busbarRef.resolve(network, TopologyLevel.BUS_BREAKER).orElseThrow(AssertionError::new));

Identifiable branch = mock(Branch.class);
when(network.getIdentifiable(eq("branchId"))).thenReturn(branch);
try {
new IdBasedBusRef("branchId").resolve(network, TopologyLevel.BUS_BRANCH);
fail();
} catch (Exception e) {
assertEquals("branchId is not a bus or injection.", e.getMessage());
}

try {
new IdBasedBusRef("branchId").resolve(network, TopologyLevel.NODE_BREAKER);
fail();
} catch (Exception e) {
assertEquals("NODE_BREAKER is not supported in resolve a BusRef.", e.getMessage());
}
}

@Test
public void testBranch() throws JsonProcessingException {
Network network = mock(Network.class);
Branch branch = mock(Branch.class);
when(network.getBranch(eq("branchId"))).thenReturn(branch);
Terminal terminal = mock(Terminal.class);
Terminal.BusView bv = mock(Terminal.BusView.class);
when(branch.getTerminal1()).thenReturn(terminal);
when(terminal.getBusView()).thenReturn(bv);
when(bv.getBus()).thenReturn(bvBus);
final BusRef busRef = new IdBasedBusRef("branchId", Branch.Side.ONE);
assertEquals(bvBus, busRef.resolve(network, TopologyLevel.BUS_BRANCH).orElseThrow(AssertionError::new));
Terminal terminal2 = mock(Terminal.class);
Terminal.BusView bv2 = mock(Terminal.BusView.class);
when(branch.getTerminal2()).thenReturn(terminal2);
when(terminal2.getBusView()).thenReturn(bv2);
Bus bus2 = mock(Bus.class);
when(bv2.getBus()).thenReturn(bus2);
final BusRef busRef2 = new IdBasedBusRef("branchId", Branch.Side.TWO);
assertEquals(bus2, busRef2.resolve(network, TopologyLevel.BUS_BRANCH).orElseThrow(AssertionError::new));

ObjectMapper objectMapper = new ObjectMapper();
final String json = objectMapper.writeValueAsString(busRef);
assertEquals("{\"@c\":\".IdBasedBusRef\",\"id\":\"branchId\",\"side\":\"ONE\"}", json);
final BusRef deserialized = objectMapper.readValue(json, BusRef.class);
assertEquals(busRef, deserialized);

assertEquals(busRef, new IdBasedBusRef("branchId", Branch.Side.ONE));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 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/.
*/
package com.powsybl.sensitivity.factors;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.powsybl.sensitivity.SensitivityFactor;
import com.powsybl.sensitivity.factors.functions.BusVoltage;
import com.powsybl.sensitivity.factors.variables.TargetVoltage;

/**
* Sensitivity factor for an impact of a targetV increase from a regulating equipment on a bus ref
*
* @author Anne Tilloy {@literal <anne.tilloy at rte-france.com>}
* @see com.powsybl.sensitivity.factors.functions.BusVoltage
* @see com.powsybl.sensitivity.factors.variables.TargetVoltage
*/
public class BusVoltagePerTargetV extends SensitivityFactor<BusVoltage, TargetVoltage> {

/**
* Sensitivity factor standard implementation constructor.
*
* @param sensitivityFunction sensitivity function
* @param sensitivityVariable sensitivity variable
*/
@JsonCreator
public BusVoltagePerTargetV(@JsonProperty("function") BusVoltage sensitivityFunction,
@JsonProperty("variable") TargetVoltage sensitivityVariable) {
super(sensitivityFunction, sensitivityVariable);
}
}
Loading

0 comments on commit dfd1c5c

Please sign in to comment.