-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BusVoltagePerTargetV sensitivity factor (#1640)
Signed-off-by: Anne Tilloy <[email protected]> Co-authored-by: yichen88 <[email protected]> Co-authored-by: Sylvain Leclerc <[email protected]>
- Loading branch information
1 parent
68407a5
commit dfd1c5c
Showing
10 changed files
with
619 additions
and
0 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
iidm/iidm-api/src/main/java/com/powsybl/iidm/network/AbstractBusRef.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
26
iidm/iidm-api/src/main/java/com/powsybl/iidm/network/BusRef.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
107 changes: 107 additions & 0 deletions
107
iidm/iidm-api/src/main/java/com/powsybl/iidm/network/IdBasedBusRef.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
125
iidm/iidm-api/src/test/java/com/powsybl/iidm/network/BusRefTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
...vity-analysis-api/src/main/java/com/powsybl/sensitivity/factors/BusVoltagePerTargetV.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
Oops, something went wrong.