AbstractAcDcConverterTest.java

/**
 * Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/)
 * 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.iidm.network.tck;

import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

import static org.junit.jupiter.api.Assertions.*;

/**
 * @author Damien Jeandemange {@literal <damien.jeandemange at artelys.com>}
 */
public abstract class AbstractAcDcConverterTest {

    private Network network;
    private VoltageLevel vla;
    private VoltageLevel vlax;
    private Bus b1a;
    private Bus b2a;
    private Bus b1ax;
    private Bus b2ax;
    private Load lax;
    private Line lineax;
    private DcNode dcNode1a;
    private DcNode dcNode2a;
    private VoltageLevel vlb;
    private VoltageLevel vlbx;
    private Bus b1b;
    private Bus b2b;
    private Bus b1bx;
    private Bus b2bx;
    private Line linebx;
    private DcNode dcNode1b;
    private DcNode dcNode2b;
    private AcDcConverter<?> acDcConverterA;
    private AcDcConverter<?> acDcConverterB;

    @BeforeEach
    void setup() {
        network = Network.create("test", "test");
        Substation sa = network.newSubstation().setId("SA").add();
        vla = sa.newVoltageLevel().setId("VLA").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(175).add();
        b1a = vla.getBusBreakerView().newBus().setId("B1A").add();
        b2a = vla.getBusBreakerView().newBus().setId("B2A").add();
        dcNode1a = network.newDcNode().setId("dcNode1a").setNominalV(1.).add();
        dcNode2a = network.newDcNode().setId("dcNode2a").setNominalV(500.).add();
        Substation sb = network.newSubstation().setId("SB").add();
        vlb = sb.newVoltageLevel().setId("VLB").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(175).add();
        b1b = vlb.getBusBreakerView().newBus().setId("B1B").add();
        b2b = vlb.getBusBreakerView().newBus().setId("B2B").add();
        dcNode1b = network.newDcNode().setId("dcNode1b").setNominalV(1.).add();
        dcNode2b = network.newDcNode().setId("dcNode2b").setNominalV(500.).add();

        vlax = sa.newVoltageLevel().setId("VLA400").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(400).add();
        b1ax = vlax.getBusBreakerView().newBus().setId("B1AX").add();
        b2ax = vlax.getBusBreakerView().newBus().setId("B2AX").add();

        lax = vlax.newLoad()
                .setId("LAX")
                .setBus(b1ax.getId())
                .setP0(0.0).setQ0(0.0)
                .add();
        lineax = network.newLine()
                .setId("LINEAX")
                .setVoltageLevel1(vlax.getId())
                .setBus1(b1ax.getId())
                .setConnectableBus1(b1ax.getId())
                .setVoltageLevel2(vlax.getId())
                .setBus2(b2ax.getId())
                .setConnectableBus2(b2ax.getId())
                .setR(0.3)
                .setX(3.0)
                .setG1(0.0)
                .setB1(0.0)
                .setG2(0.0)
                .setB2(0.0)
                .add();
        sa.newTwoWindingsTransformer()
                .setId("TRA1")
                .setVoltageLevel1(vlax.getId())
                .setBus1(b1ax.getId())
                .setConnectableBus1(b1ax.getId())
                .setRatedU1(400.0)
                .setVoltageLevel2(vla.getId())
                .setBus2(b1a.getId())
                .setConnectableBus2(b1a.getId())
                .setRatedU2(150)
                .setR(0.1)
                .setX(5.0)
                .setG(0.0)
                .setB(0.0)
                .add();
        sa.newTwoWindingsTransformer()
                .setId("TRA2")
                .setVoltageLevel1(vlax.getId())
                .setBus1(b1ax.getId())
                .setConnectableBus1(b1ax.getId())
                .setRatedU1(400.0)
                .setVoltageLevel2(vla.getId())
                .setBus2(b2a.getId())
                .setConnectableBus2(b2a.getId())
                .setRatedU2(150)
                .setR(0.1)
                .setX(5.0)
                .setG(0.0)
                .setB(0.0)
                .add();

        vlbx = sb.newVoltageLevel().setId("VLB400").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(400).add();
        b1bx = vlbx.getBusBreakerView().newBus().setId("B1BX").add();
        b2bx = vlbx.getBusBreakerView().newBus().setId("B2BX").add();

        linebx = network.newLine()
                .setId("LINEBX")
                .setVoltageLevel1(vlbx.getId())
                .setBus1(b1bx.getId())
                .setConnectableBus1(b1bx.getId())
                .setVoltageLevel2(vlbx.getId())
                .setBus2(b2bx.getId())
                .setConnectableBus2(b2bx.getId())
                .setR(0.3)
                .setX(3.0)
                .setG1(0.0)
                .setB1(0.0)
                .setG2(0.0)
                .setB2(0.0)
                .add();
        sb.newTwoWindingsTransformer()
                .setId("TRB1")
                .setVoltageLevel1(vlbx.getId())
                .setBus1(b1bx.getId())
                .setConnectableBus1(b1bx.getId())
                .setRatedU1(400.0)
                .setVoltageLevel2(vlb.getId())
                .setBus2(b1b.getId())
                .setConnectableBus2(b1b.getId())
                .setRatedU2(150)
                .setR(0.1)
                .setX(5.0)
                .setG(0.0)
                .setB(0.0)
                .add();
        sb.newTwoWindingsTransformer()
                .setId("TRB2")
                .setVoltageLevel1(vlbx.getId())
                .setBus1(b1bx.getId())
                .setConnectableBus1(b1bx.getId())
                .setRatedU1(400.0)
                .setVoltageLevel2(vlb.getId())
                .setBus2(b2b.getId())
                .setConnectableBus2(b2b.getId())
                .setRatedU2(150)
                .setR(0.1)
                .setX(5.0)
                .setG(0.0)
                .setB(0.0)
                .add();
    }

    @Test
    public void testBaseLcc() {
        acDcConverterA = createLccA(vla);
        assertEquals(1, network.getLineCommutatedConverterCount());
        assertSame(IdentifiableType.LINE_COMMUTATED_CONVERTER, acDcConverterA.getType());
        acDcConverterB = createLccB(vlb);
        assertSame(IdentifiableType.LINE_COMMUTATED_CONVERTER, acDcConverterB.getType());
        assertEquals(2, network.getLineCommutatedConverterCount());

        checkBaseCommonLccVsc();

        // default values
        assertSame(LineCommutatedConverter.ReactiveModel.FIXED_POWER_FACTOR, ((LineCommutatedConverter) acDcConverterA).getReactiveModel());
        assertEquals(0.894427191, ((LineCommutatedConverter) acDcConverterA).getPowerFactor(), 1e-4);
        // explicitly set values
        assertSame(LineCommutatedConverter.ReactiveModel.CALCULATED_POWER_FACTOR, ((LineCommutatedConverter) acDcConverterB).getReactiveModel());
        assertEquals(0.6, ((LineCommutatedConverter) acDcConverterB).getPowerFactor());

        List<LineCommutatedConverter> dcConverterList = List.of((LineCommutatedConverter) acDcConverterA, (LineCommutatedConverter) acDcConverterB);
        assertEquals(2, ((Collection<?>) network.getLineCommutatedConverters()).size());
        network.getLineCommutatedConverters().forEach(dcConverter -> assertTrue(dcConverterList.contains(dcConverter)));
        network.getLineCommutatedConverterStream().forEach(dcConverter -> assertTrue(dcConverterList.contains(dcConverter)));
        assertEquals(2, network.getIdentifiableStream(IdentifiableType.LINE_COMMUTATED_CONVERTER).count());
        network.getIdentifiableStream(IdentifiableType.LINE_COMMUTATED_CONVERTER).forEach(dcConverter -> assertTrue(dcConverterList.contains((LineCommutatedConverter) dcConverter)));
        assertEquals(1, vla.getLineCommutatedConverterCount());
        assertEquals(1, ((Collection<?>) vla.getLineCommutatedConverters()).size());
        vla.getLineCommutatedConverters().forEach(dcConverter -> assertSame(acDcConverterA, dcConverter));
        vla.getLineCommutatedConverterStream().forEach(dcConverter -> assertSame(acDcConverterA, dcConverter));
        assertEquals(1, vlb.getLineCommutatedConverterCount());
        assertEquals(1, ((Collection<?>) vlb.getLineCommutatedConverters()).size());
        vlb.getLineCommutatedConverters().forEach(dcConverter -> assertSame(acDcConverterB, dcConverter));
        vlb.getLineCommutatedConverterStream().forEach(dcConverter -> assertSame(acDcConverterB, dcConverter));
    }

    @Test
    public void testBaseVsc() {
        acDcConverterA = createVscA(vla);
        assertEquals(1, network.getVoltageSourceConverterCount());
        assertSame(IdentifiableType.VOLTAGE_SOURCE_CONVERTER, acDcConverterA.getType());
        acDcConverterB = createVscB(vlb);
        assertSame(IdentifiableType.VOLTAGE_SOURCE_CONVERTER, acDcConverterB.getType());
        assertEquals(2, network.getVoltageSourceConverterCount());

        checkBaseCommonLccVsc();

        List<VoltageSourceConverter> dcConverterList = List.of((VoltageSourceConverter) acDcConverterA, (VoltageSourceConverter) acDcConverterB);
        assertEquals(2, ((Collection<?>) network.getVoltageSourceConverters()).size());
        network.getVoltageSourceConverters().forEach(dcConverter -> assertTrue(dcConverterList.contains(dcConverter)));
        network.getVoltageSourceConverterStream().forEach(dcConverter -> assertTrue(dcConverterList.contains(dcConverter)));
        assertEquals(2, network.getIdentifiableStream(IdentifiableType.VOLTAGE_SOURCE_CONVERTER).count());
        network.getIdentifiableStream(IdentifiableType.VOLTAGE_SOURCE_CONVERTER).forEach(dcConverter -> assertTrue(dcConverterList.contains((VoltageSourceConverter) dcConverter)));
        assertEquals(1, vla.getVoltageSourceConverterCount());
        assertEquals(1, ((Collection<?>) vla.getVoltageSourceConverters()).size());
        vla.getVoltageSourceConverters().forEach(dcConverter -> assertSame(acDcConverterA, dcConverter));
        vla.getVoltageSourceConverterStream().forEach(dcConverter -> assertSame(acDcConverterA, dcConverter));
        assertEquals(1, vlb.getVoltageSourceConverterCount());
        assertEquals(1, ((Collection<?>) vlb.getVoltageSourceConverters()).size());
        vlb.getVoltageSourceConverters().forEach(dcConverter -> assertSame(acDcConverterB, dcConverter));
        vlb.getVoltageSourceConverterStream().forEach(dcConverter -> assertSame(acDcConverterB, dcConverter));
    }

    private void checkBaseCommonLccVsc() {
        assertEquals("converterA", acDcConverterA.getId());

        assertSame(TwoSides.ONE, acDcConverterA.getDcTerminal1().getSide());
        assertSame(TwoSides.TWO, acDcConverterA.getDcTerminal2().getSide());
        assertSame(TwoSides.ONE, acDcConverterA.getSide(acDcConverterA.getDcTerminal1()));
        assertSame(TwoSides.TWO, acDcConverterA.getSide(acDcConverterA.getDcTerminal2()));
        assertSame(acDcConverterA.getDcTerminal1(), acDcConverterA.getDcTerminal(TwoSides.ONE));
        assertSame(acDcConverterA.getDcTerminal2(), acDcConverterA.getDcTerminal(TwoSides.TWO));

        assertSame(ThreeSides.ONE, acDcConverterA.getTerminal1().getSide());
        assertSame(ThreeSides.TWO, acDcConverterA.getTerminal2().orElseThrow().getSide());
        assertSame(TwoSides.ONE, acDcConverterA.getSide(acDcConverterA.getTerminal1()));
        assertSame(TwoSides.TWO, acDcConverterA.getSide(acDcConverterA.getTerminal2().orElseThrow()));
        assertSame(acDcConverterA.getTerminal1(), acDcConverterA.getTerminal(TwoSides.ONE));
        assertSame(acDcConverterA.getTerminal2().orElseThrow(), acDcConverterA.getTerminal(TwoSides.TWO));
        assertSame(ThreeSides.ONE, Terminal.getConnectableSide(acDcConverterA.getTerminal1()).orElseThrow());
        assertSame(ThreeSides.TWO, Terminal.getConnectableSide(acDcConverterA.getTerminal2().orElseThrow()).orElseThrow());
        assertSame(acDcConverterA.getTerminal1(), Terminal.getTerminal(acDcConverterA, ThreeSides.ONE));
        assertSame(acDcConverterA.getTerminal2().orElseThrow(), Terminal.getTerminal(acDcConverterA, ThreeSides.TWO));

        assertSame(b1a, acDcConverterA.getTerminal1().getBusBreakerView().getBus());
        assertTrue(acDcConverterA.getTerminal2().isPresent());
        assertSame(b2a, acDcConverterA.getTerminal2().orElseThrow().getBusBreakerView().getBus());
        assertTrue(acDcConverterA.getDcTerminal1().isConnected());
        assertTrue(acDcConverterA.getDcTerminal2().isConnected());
        assertEquals(2, acDcConverterA.getDcTerminals().size());
        assertSame(acDcConverterA.getDcTerminals().get(0), acDcConverterA.getDcTerminal1());
        assertSame(acDcConverterA.getDcTerminals().get(1), acDcConverterA.getDcTerminal2());
        assertSame(dcNode1a, acDcConverterA.getDcTerminal1().getDcNode());
        assertSame(dcNode2a, acDcConverterA.getDcTerminal2().getDcNode());
        assertSame(acDcConverterA, acDcConverterA.getDcTerminal1().getDcConnectable());
        assertSame(acDcConverterA, acDcConverterA.getDcTerminal2().getDcConnectable());
        assertEquals(0.01, acDcConverterA.getIdleLoss());
        assertEquals(0.02, acDcConverterA.getSwitchingLoss());
        assertEquals(0.03, acDcConverterA.getResistiveLoss());

        assertEquals("converterB", acDcConverterB.getId());
        assertFalse(acDcConverterB.getDcTerminal1().isConnected());
        assertFalse(acDcConverterB.getDcTerminal2().isConnected());
        assertSame(dcNode1b, acDcConverterB.getDcTerminal1().getDcNode());
        assertSame(dcNode2b, acDcConverterB.getDcTerminal2().getDcNode());
    }

    private LineCommutatedConverterAdder createLccAdder(VoltageLevel voltageLevel) {
        return voltageLevel.newLineCommutatedConverter()
                .setIdleLoss(0.01)
                .setSwitchingLoss(0.02)
                .setResistiveLoss(0.03)
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.);
    }

    private LineCommutatedConverter createLccA(VoltageLevel voltageLevel) {
        return createLccAdder(voltageLevel)
                .setId("converterA")
                .setBus1(b1a.getId())
                .setConnectableBus1(b1a.getId())
                .setBus2(b2a.getId())
                .setConnectableBus2(b2a.getId())
                .setDcNode1(dcNode1a.getId())
                .setDcNode2(dcNode2a.getId())
                .setDcConnected1(true)
                .setDcConnected2(true)
                .setPccTerminal(lineax.getTerminal1())
                .add();
    }

    private LineCommutatedConverter createLccB(VoltageLevel voltageLevel) {
        return createLccAdder(voltageLevel)
                .setId("converterB")
                .setBus1(b1b.getId())
                .setBus2(b2b.getId())
                .setDcNode1(dcNode1b.getId())
                .setDcNode2(dcNode2b.getId())
                .setDcConnected1(false)
                .setDcConnected2(false)
                .setPccTerminal(linebx.getTerminal1())
                .setReactiveModel(LineCommutatedConverter.ReactiveModel.CALCULATED_POWER_FACTOR)
                .setPowerFactor(0.6)
                .add();
    }

    private VoltageSourceConverterAdder createVscAdder(VoltageLevel voltageLevel) {
        return voltageLevel.newVoltageSourceConverter()
                .setIdleLoss(0.01)
                .setSwitchingLoss(0.02)
                .setResistiveLoss(0.03)
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.);
    }

    private VoltageSourceConverter createVscA(VoltageLevel voltageLevel) {
        return createVscAdder(voltageLevel)
                .setId("converterA")
                .setBus1(b1a.getId())
                .setBus2(b2a.getId())
                .setDcNode1(dcNode1a.getId())
                .setDcNode2(dcNode2a.getId())
                .setDcConnected1(true)
                .setDcConnected2(true)
                .setPccTerminal(lineax.getTerminal1())
                .setVoltageRegulatorOn(false)
                .setReactivePowerSetpoint(0.0)
                .add();
    }

    private VoltageSourceConverter createVscB(VoltageLevel voltageLevel) {
        return createVscAdder(voltageLevel)
                .setId("converterB")
                .setBus1(b1b.getId())
                .setBus2(b2b.getId())
                .setDcNode1(dcNode1b.getId())
                .setDcNode2(dcNode2b.getId())
                .setDcConnected1(false)
                .setDcConnected2(false)
                .setPccTerminal(linebx.getTerminal1())
                .setVoltageRegulatorOn(false)
                .setReactivePowerSetpoint(0.0)
                .add();
    }

    @Test
    public void testLossParametersGetterSetter() {
        acDcConverterA = createLccA(vla);
        assertEquals(0.01, acDcConverterA.getIdleLoss());
        assertEquals(0.02, acDcConverterA.getSwitchingLoss());
        assertEquals(0.03, acDcConverterA.getResistiveLoss());
        acDcConverterA
                .setIdleLoss(0.04)
                .setSwitchingLoss(0.05)
                .setResistiveLoss(0.06);
        assertEquals(0.04, acDcConverterA.getIdleLoss());
        assertEquals(0.05, acDcConverterA.getSwitchingLoss());
        assertEquals(0.06, acDcConverterA.getResistiveLoss());
        acDcConverterA
                .setIdleLoss(0.)
                .setSwitchingLoss(0.)
                .setResistiveLoss(0.);
        assertEquals(0., acDcConverterA.getIdleLoss());
        assertEquals(0., acDcConverterA.getSwitchingLoss());
        assertEquals(0., acDcConverterA.getResistiveLoss());

        PowsyblException e1 = assertThrows(PowsyblException.class, () -> acDcConverterA.setIdleLoss(Double.NaN));
        assertEquals("AC/DC Line Commutated Converter 'converterA': idleLoss is invalid", e1.getMessage());

        PowsyblException e2 = assertThrows(PowsyblException.class, () -> acDcConverterA.setIdleLoss(-1.0));
        assertEquals("AC/DC Line Commutated Converter 'converterA': idleLoss is invalid", e2.getMessage());

        PowsyblException e3 = assertThrows(PowsyblException.class, () -> acDcConverterA.setSwitchingLoss(Double.NaN));
        assertEquals("AC/DC Line Commutated Converter 'converterA': switchingLoss is invalid", e3.getMessage());

        PowsyblException e4 = assertThrows(PowsyblException.class, () -> acDcConverterA.setSwitchingLoss(-1.0));
        assertEquals("AC/DC Line Commutated Converter 'converterA': switchingLoss is invalid", e4.getMessage());

        PowsyblException e5 = assertThrows(PowsyblException.class, () -> acDcConverterA.setResistiveLoss(Double.NaN));
        assertEquals("AC/DC Line Commutated Converter 'converterA': resistiveLoss is invalid", e5.getMessage());

        PowsyblException e6 = assertThrows(PowsyblException.class, () -> acDcConverterA.setResistiveLoss(-1.0));
        assertEquals("AC/DC Line Commutated Converter 'converterA': resistiveLoss is invalid", e6.getMessage());
    }

    @Test
    public void testLccGetterSetter() {
        acDcConverterA = createLccA(vla);
        LineCommutatedConverter lccA = (LineCommutatedConverter) acDcConverterA;

        assertEquals(0.894427191, lccA.getPowerFactor(), 1e-4);
        assertEquals(LineCommutatedConverter.ReactiveModel.FIXED_POWER_FACTOR, lccA.getReactiveModel());

        lccA.setPowerFactor(0.85).setReactiveModel(LineCommutatedConverter.ReactiveModel.CALCULATED_POWER_FACTOR);
        assertEquals(0.85, lccA.getPowerFactor());
        assertEquals(LineCommutatedConverter.ReactiveModel.CALCULATED_POWER_FACTOR, lccA.getReactiveModel());

        PowsyblException e1 = assertThrows(PowsyblException.class, () -> lccA.setPowerFactor(-0.1));
        assertEquals("AC/DC Line Commutated Converter 'converterA': power factor is invalid, it must be between 0 and 1", e1.getMessage());

        PowsyblException e2 = assertThrows(PowsyblException.class, () -> lccA.setPowerFactor(1.1));
        assertEquals("AC/DC Line Commutated Converter 'converterA': power factor is invalid, it must be between 0 and 1", e2.getMessage());

        PowsyblException e3 = assertThrows(PowsyblException.class, () -> lccA.setPowerFactor(Double.NaN));
        assertEquals("AC/DC Line Commutated Converter 'converterA': power factor is invalid", e3.getMessage());

        PowsyblException e4 = assertThrows(PowsyblException.class, () -> lccA.setReactiveModel(null));
        assertEquals("AC/DC Line Commutated Converter 'converterA': reactiveModel is not set", e4.getMessage());
    }

    @Test
    public void testCreateDuplicate() {
        acDcConverterA = createLccA(vla);

        PowsyblException exception = assertThrows(PowsyblException.class, () -> createLccA(vla));
        assertTrue(Pattern.compile("The network test already contains an object '(\\w+)' with the id 'converterA'").matcher(exception.getMessage()).find());
    }

    @Test
    public void testRemoveLcc() {
        acDcConverterA = createLccA(vla);
        DcTerminal t1 = acDcConverterA.getDcTerminal1();
        DcTerminal t2 = acDcConverterA.getDcTerminal2();
        acDcConverterB = createLccB(vlb);
        assertEquals(2, network.getLineCommutatedConverterCount());
        assertEquals(1, vla.getLineCommutatedConverterCount());
        assertEquals(1, vlb.getLineCommutatedConverterCount());
        acDcConverterA.remove();
        assertNull(network.getLineCommutatedConverter(acDcConverterA.getId()));
        assertEquals(1, network.getLineCommutatedConverterCount());
        assertEquals(0, vla.getLineCommutatedConverterCount());
        assertEquals(0, ((Collection<?>) vla.getLineCommutatedConverters()).size());
        acDcConverterB.remove();
        assertNull(network.getLineCommutatedConverter(acDcConverterB.getId()));
        assertEquals(0, network.getLineCommutatedConverterCount());
        assertEquals(0, vlb.getLineCommutatedConverterCount());
        assertEquals(0, ((Collection<?>) vlb.getLineCommutatedConverters()).size());

        checkCommonRemoveLccVsc(t1, t2);
    }

    @Test
    public void testRemoveVsc() {
        acDcConverterA = createVscA(vla);
        DcTerminal t1 = acDcConverterA.getDcTerminal1();
        DcTerminal t2 = acDcConverterA.getDcTerminal2();
        acDcConverterB = createVscB(vlb);
        assertEquals(2, network.getVoltageSourceConverterCount());
        assertEquals(1, vla.getVoltageSourceConverterCount());
        assertEquals(1, vlb.getVoltageSourceConverterCount());
        acDcConverterA.remove();
        assertNull(network.getLineCommutatedConverter(acDcConverterA.getId()));
        assertEquals(1, network.getVoltageSourceConverterCount());
        assertEquals(0, vla.getVoltageSourceConverterCount());
        assertEquals(0, ((Collection<?>) vla.getVoltageSourceConverters()).size());
        acDcConverterB.remove();
        assertNull(network.getLineCommutatedConverter(acDcConverterB.getId()));
        assertEquals(0, network.getVoltageSourceConverterCount());
        assertEquals(0, vlb.getVoltageSourceConverterCount());
        assertEquals(0, ((Collection<?>) vlb.getVoltageSourceConverters()).size());

        checkCommonRemoveLccVsc(t1, t2);
    }

    private void checkCommonRemoveLccVsc(DcTerminal t1, DcTerminal t2) {
        PowsyblException e1 = assertThrows(PowsyblException.class, () -> acDcConverterA.setIdleLoss(2.));
        assertEquals("Cannot modify idleLoss of removed equipment converterA", e1.getMessage());

        PowsyblException e2 = assertThrows(PowsyblException.class, acDcConverterA::getIdleLoss);
        assertEquals("Cannot access idleLoss of removed equipment converterA", e2.getMessage());

        PowsyblException e3 = assertThrows(PowsyblException.class, () -> acDcConverterA.setSwitchingLoss(2.));
        assertEquals("Cannot modify switchingLoss of removed equipment converterA", e3.getMessage());

        PowsyblException e4 = assertThrows(PowsyblException.class, acDcConverterA::getSwitchingLoss);
        assertEquals("Cannot access switchingLoss of removed equipment converterA", e4.getMessage());

        PowsyblException e5 = assertThrows(PowsyblException.class, () -> acDcConverterA.setResistiveLoss(2.));
        assertEquals("Cannot modify resistiveLoss of removed equipment converterA", e5.getMessage());

        PowsyblException e6 = assertThrows(PowsyblException.class, acDcConverterA::getResistiveLoss);
        assertEquals("Cannot access resistiveLoss of removed equipment converterA", e6.getMessage());

        PowsyblException e7 = assertThrows(PowsyblException.class, t1::isConnected);
        assertEquals("Cannot access removed equipment converterA", e7.getMessage());

        PowsyblException e8 = assertThrows(PowsyblException.class, () -> t2.setConnected(false));
        assertEquals("Cannot modify removed equipment converterA", e8.getMessage());
    }

    @Test
    public void testOnSubnetworkLcc() {
        Network netWithSubnet = Network.create("test", "test");

        Network subnetwork1 = netWithSubnet.createSubnetwork("subnetwork1", "subnetwork1", "format1");
        Network subnetwork2 = netWithSubnet.createSubnetwork("subnetwork2", "subnetwork2", "format2");
        Substation sSubnet1 = subnetwork1.newSubstation().setId("SSubnetwork1").add();
        VoltageLevel vlSubnet1 = sSubnet1.newVoltageLevel().setId("VLSubnet1").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(175).add();
        Bus b1Subnet1 = vlSubnet1.getBusBreakerView().newBus().setId("B1Subnet1").add();
        DcNode dcNode1Subnet1 = subnetwork1.newDcNode().setId("dcNode1Subnet1").setNominalV(1.).add();
        DcNode dcNode2Subnet1 = subnetwork1.newDcNode().setId("dcNode2Subnet1").setNominalV(500.).add();
        Substation sSubnet2 = subnetwork2.newSubstation().setId("SSubnetwork2").add();
        VoltageLevel vlSubnet2 = sSubnet2.newVoltageLevel().setId("VLSubnet2").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(175).add();
        Bus b1Subnet2 = vlSubnet2.getBusBreakerView().newBus().setId("B1Subnet2").add();
        DcNode dcNode1Subnet2 = subnetwork2.newDcNode().setId("dcNode1Subnet2").setNominalV(1.).add();
        DcNode dcNode2Subnet2 = subnetwork2.newDcNode().setId("dcNode2Subnet2").setNominalV(500.).add();

        LineCommutatedConverter converterSubnet1 = vlSubnet1
                .newLineCommutatedConverter()
                .setId("converterSubnet1")
                .setBus1(b1Subnet1.getId())
                .setDcNode1(dcNode1Subnet1.getId())
                .setDcNode2(dcNode2Subnet1.getId())
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.)
                .add();
        LineCommutatedConverter converterSubnet2 = vlSubnet2
                .newLineCommutatedConverter()
                .setId("converterSubnet2")
                .setBus1(b1Subnet2.getId())
                .setDcNode1(dcNode1Subnet2.getId())
                .setDcNode2(dcNode2Subnet2.getId())
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.)
                .add();

        List<LineCommutatedConverter> dcConverterList = List.of(converterSubnet1, converterSubnet2);

        // network content
        assertEquals(2, ((Collection<?>) netWithSubnet.getLineCommutatedConverters()).size());
        netWithSubnet.getLineCommutatedConverters().forEach(converter -> assertTrue(dcConverterList.contains(converter)));
        netWithSubnet.getLineCommutatedConverterStream().forEach(converter -> assertTrue(dcConverterList.contains(converter)));
        assertEquals(2, netWithSubnet.getIdentifiableStream(IdentifiableType.LINE_COMMUTATED_CONVERTER).count());
        netWithSubnet.getIdentifiableStream(IdentifiableType.LINE_COMMUTATED_CONVERTER).forEach(converter -> assertTrue(dcConverterList.contains((LineCommutatedConverter) converter)));
        assertEquals(2, netWithSubnet.getLineCommutatedConverterCount());
        assertSame(converterSubnet1, netWithSubnet.getLineCommutatedConverter(converterSubnet1.getId()));
        assertSame(converterSubnet2, netWithSubnet.getLineCommutatedConverter(converterSubnet2.getId()));

        // subnetwork1 content
        assertEquals(1, ((Collection<?>) subnetwork1.getLineCommutatedConverters()).size());
        subnetwork1.getLineCommutatedConverters().forEach(converter -> assertSame(converterSubnet1, converter));
        subnetwork1.getLineCommutatedConverterStream().forEach(converter -> assertSame(converterSubnet1, converter));
        assertEquals(1, subnetwork1.getIdentifiableStream(IdentifiableType.LINE_COMMUTATED_CONVERTER).count());
        subnetwork1.getIdentifiableStream(IdentifiableType.LINE_COMMUTATED_CONVERTER).forEach(converter -> assertSame(converterSubnet1, converter));
        assertEquals(1, subnetwork1.getLineCommutatedConverterCount());
        assertSame(converterSubnet1, subnetwork1.getLineCommutatedConverter(converterSubnet1.getId()));
        assertNull(subnetwork1.getLineCommutatedConverter(converterSubnet2.getId()));

        // subnetwork2 content
        assertEquals(1, ((Collection<?>) subnetwork2.getLineCommutatedConverters()).size());
        subnetwork2.getLineCommutatedConverters().forEach(converter -> assertSame(converterSubnet2, converter));
        subnetwork2.getLineCommutatedConverterStream().forEach(converter -> assertSame(converterSubnet2, converter));
        assertEquals(1, subnetwork2.getIdentifiableStream(IdentifiableType.LINE_COMMUTATED_CONVERTER).count());
        subnetwork2.getIdentifiableStream(IdentifiableType.LINE_COMMUTATED_CONVERTER).forEach(converter -> assertSame(converterSubnet2, converter));
        assertEquals(1, subnetwork2.getLineCommutatedConverterCount());
        assertSame(converterSubnet2, subnetwork2.getLineCommutatedConverter(converterSubnet2.getId()));
        assertNull(subnetwork2.getLineCommutatedConverter(converterSubnet1.getId()));
    }

    @Test
    public void testOnSubnetworkVsc() {
        Network netWithSubnet = Network.create("test", "test");

        Network subnetwork1 = netWithSubnet.createSubnetwork("subnetwork1", "subnetwork1", "format1");
        Network subnetwork2 = netWithSubnet.createSubnetwork("subnetwork2", "subnetwork2", "format2");
        Substation sSubnet1 = subnetwork1.newSubstation().setId("SSubnetwork1").add();
        VoltageLevel vlSubnet1 = sSubnet1.newVoltageLevel().setId("VLSubnet1").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(175).add();
        Bus b1Subnet1 = vlSubnet1.getBusBreakerView().newBus().setId("B1Subnet1").add();
        DcNode dcNode1Subnet1 = subnetwork1.newDcNode().setId("dcNode1Subnet1").setNominalV(1.).add();
        DcNode dcNode2Subnet1 = subnetwork1.newDcNode().setId("dcNode2Subnet1").setNominalV(500.).add();
        Substation sSubnet2 = subnetwork2.newSubstation().setId("SSubnetwork2").add();
        VoltageLevel vlSubnet2 = sSubnet2.newVoltageLevel().setId("VLSubnet2").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(175).add();
        Bus b1Subnet2 = vlSubnet2.getBusBreakerView().newBus().setId("B1Subnet2").add();
        DcNode dcNode1Subnet2 = subnetwork2.newDcNode().setId("dcNode1Subnet2").setNominalV(1.).add();
        DcNode dcNode2Subnet2 = subnetwork2.newDcNode().setId("dcNode2Subnet2").setNominalV(500.).add();

        VoltageSourceConverter converterSubnet1 = vlSubnet1
                .newVoltageSourceConverter()
                .setId("converterSubnet1")
                .setBus1(b1Subnet1.getId())
                .setDcNode1(dcNode1Subnet1.getId())
                .setDcNode2(dcNode2Subnet1.getId())
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.)
                .setVoltageRegulatorOn(false)
                .setReactivePowerSetpoint(0.0)
                .add();
        VoltageSourceConverter converterSubnet2 = vlSubnet2
                .newVoltageSourceConverter()
                .setId("converterSubnet2")
                .setBus1(b1Subnet2.getId())
                .setDcNode1(dcNode1Subnet2.getId())
                .setDcNode2(dcNode2Subnet2.getId())
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.)
                .setVoltageRegulatorOn(false)
                .setReactivePowerSetpoint(0.0)
                .add();

        List<VoltageSourceConverter> dcConverterList = List.of(converterSubnet1, converterSubnet2);

        // network content
        assertEquals(2, ((Collection<?>) netWithSubnet.getVoltageSourceConverters()).size());
        netWithSubnet.getVoltageSourceConverters().forEach(converter -> assertTrue(dcConverterList.contains(converter)));
        netWithSubnet.getVoltageSourceConverterStream().forEach(converter -> assertTrue(dcConverterList.contains(converter)));
        assertEquals(2, netWithSubnet.getIdentifiableStream(IdentifiableType.VOLTAGE_SOURCE_CONVERTER).count());
        netWithSubnet.getIdentifiableStream(IdentifiableType.VOLTAGE_SOURCE_CONVERTER).forEach(converter -> assertTrue(dcConverterList.contains((VoltageSourceConverter) converter)));
        assertEquals(2, netWithSubnet.getVoltageSourceConverterCount());
        assertSame(converterSubnet1, netWithSubnet.getVoltageSourceConverter(converterSubnet1.getId()));
        assertSame(converterSubnet2, netWithSubnet.getVoltageSourceConverter(converterSubnet2.getId()));

        // subnetwork1 content
        assertEquals(1, ((Collection<?>) subnetwork1.getVoltageSourceConverters()).size());
        subnetwork1.getVoltageSourceConverters().forEach(converter -> assertSame(converterSubnet1, converter));
        subnetwork1.getVoltageSourceConverterStream().forEach(converter -> assertSame(converterSubnet1, converter));
        assertEquals(1, subnetwork1.getIdentifiableStream(IdentifiableType.VOLTAGE_SOURCE_CONVERTER).count());
        subnetwork1.getIdentifiableStream(IdentifiableType.VOLTAGE_SOURCE_CONVERTER).forEach(converter -> assertSame(converterSubnet1, converter));
        assertEquals(1, subnetwork1.getVoltageSourceConverterCount());
        assertSame(converterSubnet1, subnetwork1.getVoltageSourceConverter(converterSubnet1.getId()));
        assertNull(subnetwork2.getVoltageSourceConverter(converterSubnet1.getId()));

        // subnetwork2 content
        assertEquals(1, ((Collection<?>) subnetwork2.getVoltageSourceConverters()).size());
        subnetwork2.getVoltageSourceConverters().forEach(converter -> assertSame(converterSubnet2, converter));
        subnetwork2.getVoltageSourceConverterStream().forEach(converter -> assertSame(converterSubnet2, converter));
        assertEquals(1, subnetwork2.getIdentifiableStream(IdentifiableType.VOLTAGE_SOURCE_CONVERTER).count());
        subnetwork2.getIdentifiableStream(IdentifiableType.VOLTAGE_SOURCE_CONVERTER).forEach(converter -> assertSame(converterSubnet2, converter));
        assertEquals(1, subnetwork2.getVoltageSourceConverterCount());
        assertSame(converterSubnet2, subnetwork2.getVoltageSourceConverter(converterSubnet2.getId()));
        assertNull(subnetwork1.getVoltageSourceConverter(converterSubnet2.getId()));
    }

    @Test
    public void testNotAcrossNetworkSubnetworks() {
        Network netWithSubnet = Network.create("test", "test");

        Network subnetwork1 = netWithSubnet.createSubnetwork("subnetwork1", "subnetwork1", "format1");
        Network subnetwork2 = netWithSubnet.createSubnetwork("subnetwork2", "subnetwork2", "format2");
        Substation sSubnet1 = subnetwork1.newSubstation().setId("SSubnetwork1").add();
        VoltageLevel vlSubnet1 = sSubnet1.newVoltageLevel().setId("VLSubnet1").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(175).add();
        Bus b1Subnet1 = vlSubnet1.getBusBreakerView().newBus().setId("B1Subnet1").add();
        DcNode dcNode1Root = netWithSubnet.newDcNode().setId("dcNode1Root").setNominalV(1.).add();
        DcNode dcNode1Subnet1 = subnetwork1.newDcNode().setId("dcNode1Subnet1").setNominalV(1.).add();
        DcNode dcNode1Subnet2 = subnetwork2.newDcNode().setId("dcNode1Subnet2").setNominalV(1.).add();
        DcNode dcNode2Subnet2 = subnetwork2.newDcNode().setId("dcNode2Subnet2").setNominalV(500.).add();

        VoltageSourceConverterAdder adder = vlSubnet1
                .newVoltageSourceConverter()
                .setId("converterAcrossSubnets")
                .setBus1(b1Subnet1.getId())
                .setDcNode1(dcNode1Subnet1.getId())
                .setDcNode2(dcNode1Subnet2.getId())
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.)
                .setVoltageRegulatorOn(false)
                .setReactivePowerSetpoint(0.0);

        // test cannot create Converter across subnetwork1 & subnetwork2
        PowsyblException e1 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Voltage Source Converter 'converterAcrossSubnets': DC Nodes 'dcNode1Subnet1' and 'dcNode1Subnet2' are in different networks 'subnetwork1' and 'subnetwork2'", e1.getMessage());

        // test cannot create Converter in subnetwork1 referencing nodes of subnetwork2
        adder.setDcNode1(dcNode1Subnet2.getId()).setDcNode2(dcNode2Subnet2.getId());
        PowsyblException e2 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Voltage Source Converter 'converterAcrossSubnets': DC Nodes 'dcNode1Subnet2' and 'dcNode2Subnet2' are in network 'subnetwork2' but DC Equipment is in 'subnetwork1'", e2.getMessage());

        // test cannot create Converter in subnetwork1 referencing nodes of netWithSubnet
        adder.setDcNode1(dcNode1Subnet1.getId()).setDcNode2(dcNode1Root.getId());
        PowsyblException e3 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Voltage Source Converter 'converterAcrossSubnets': DC Nodes 'dcNode1Subnet1' and 'dcNode1Root' are in different networks 'subnetwork1' and 'test'", e3.getMessage());
    }

    @Test
    public void testVscReactiveLimits() {
        acDcConverterA = createVscA(vla);
        VoltageSourceConverter vsc = (VoltageSourceConverter) acDcConverterA;

        assertSame(ReactiveLimitsKind.MIN_MAX, vsc.getReactiveLimits().getKind());
        assertEquals(-Double.MAX_VALUE, vsc.getReactiveLimits().getMinQ(0));
        assertEquals(Double.MAX_VALUE, vsc.getReactiveLimits().getMaxQ(0));
        assertSame(vsc.getReactiveLimits(), vsc.getReactiveLimits(MinMaxReactiveLimits.class));

        vsc.newMinMaxReactiveLimits().setMinQ(-100.).setMaxQ(150.).add();
        assertEquals(-100., vsc.getReactiveLimits().getMinQ(0));
        assertEquals(150, vsc.getReactiveLimits().getMaxQ(0));

        vsc.newReactiveCapabilityCurve()
                .beginPoint().setP(-100.).setMinQ(-80).setMaxQ(70.).endPoint()
                .beginPoint().setP(0.).setMinQ(-100).setMaxQ(90.).endPoint()
                .beginPoint().setP(100.).setMinQ(-70).setMaxQ(60.).endPoint()
                .add();
        assertSame(ReactiveLimitsKind.CURVE, vsc.getReactiveLimits().getKind());
        assertEquals(-90., vsc.getReactiveLimits().getMinQ(-50));
        assertEquals(80, vsc.getReactiveLimits().getMaxQ(-50));
        assertSame(vsc.getReactiveLimits(), vsc.getReactiveLimits(ReactiveCapabilityCurve.class));
    }

    @Test
    public void testCreationError() {
        LineCommutatedConverterAdder adder = vla.newLineCommutatedConverter()
                .setId("converterA")
                .setBus1(b1a.getId())
                .setBus2(b2a.getId());

        PowsyblException e1 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': controlMode is not set", e1.getMessage());

        adder.setControlMode(AcDcConverter.ControlMode.V_DC);
        PowsyblException e2 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': targetVdc is invalid", e2.getMessage());

        adder.setControlMode(AcDcConverter.ControlMode.P_PCC);
        PowsyblException e3 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': targetP is invalid", e3.getMessage());

        adder.setTargetP(200.);
        PowsyblException e4 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': converter has two AC terminals and pccTerminal is not set", e4.getMessage());

        adder.setPccTerminal(lax.getTerminal());
        PowsyblException e5 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': converter has two AC terminals and pccTerminal is not a line or transformer terminal", e5.getMessage());

        adder.setBus2(null);
        PowsyblException e6 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': pccTerminal is not a line or transformer or the converter terminal", e6.getMessage());

        adder.setPccTerminal(lineax.getTerminal1());
        PowsyblException e7 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': dcNode1 is not set", e7.getMessage());

        adder.setDcNode1(dcNode1a.getId());
        PowsyblException e8 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': dcNode2 is not set", e8.getMessage());

        adder.setDcNode2(dcNode2a.getId());
        Network subnet = network.createSubnetwork("subNet", "subNetName", "code");
        VoltageLevel subNetVl = subnet.newVoltageLevel().setId("subNetVl").setTopologyKind(TopologyKind.BUS_BREAKER).setNominalV(400.).add();
        Bus subnetB1 = subNetVl.getBusBreakerView().newBus().setId("subNetB1").add();
        Bus subnetB2 = subNetVl.getBusBreakerView().newBus().setId("subNetB2").add();
        Line subNetLine = subnet.newLine().setId("subNetLine")
                .setBus1(subnetB1.getId())
                .setBus2(subnetB2.getId())
                .setR(0.).setX(1.0).setB1(0.).setB2(0.).setG1(0.).setG2(0.)
                .add();

        adder.setPccTerminal(subNetLine.getTerminal1());
        PowsyblException e9 = assertThrows(PowsyblException.class, adder::add);
        assertEquals("AC/DC Line Commutated Converter 'converterA': pccTerminal is not in the same parent network as the voltage level", e9.getMessage());
    }

    @Test
    public void testSingleAcTerminal() {
        acDcConverterA = vla.newVoltageSourceConverter()
                .setId("converterA")
                .setBus1(b1a.getId())
                .setDcNode1(dcNode1a.getId())
                .setDcNode2(dcNode2a.getId())
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.)
                .setVoltageRegulatorOn(false)
                .setReactivePowerSetpoint(0.0)
                .add();
        assertTrue(acDcConverterA.getTerminal2().isEmpty());
        assertSame(acDcConverterA.getPccTerminal(), acDcConverterA.getTerminal1());
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> acDcConverterA.getTerminal(TwoSides.TWO));
        assertEquals("This AC/DC converter does not have a second AC Terminal", e.getMessage());
    }

    @Test
    public void testSetterGetterInMultiVariants() {
        VoltageSourceConverter vscA = vla.newVoltageSourceConverter()
                .setId("converterA")
                .setBus1(b1a.getId())
                .setDcNode1(dcNode1a.getId())
                .setDcNode2(dcNode2a.getId())
                .setControlMode(AcDcConverter.ControlMode.P_PCC)
                .setTargetP(100.)
                .setTargetVdc(500.)
                .setVoltageRegulatorOn(false)
                .setReactivePowerSetpoint(10.0)
                .setVoltageSetpoint(400.0)
                .add();
        assertEquals(AcDcConverter.ControlMode.P_PCC, vscA.getControlMode());
        assertEquals(100.0, vscA.getTargetP(), 0.0);
        assertEquals(500.0, vscA.getTargetVdc(), 0.0);
        assertEquals(10.0, vscA.getReactivePowerSetpoint(), 0.0);
        assertEquals(400.0, vscA.getVoltageSetpoint(), 0.0);
        assertFalse(vscA.isVoltageRegulatorOn());

        List<String> variantsToAdd = Arrays.asList("s1", "s2", "s3", "s4");
        VariantManager variantManager = network.getVariantManager();
        variantManager.cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, variantsToAdd);

        variantManager.setWorkingVariant("s4");
        // check values cloned by extend
        assertEquals(AcDcConverter.ControlMode.P_PCC, vscA.getControlMode());
        assertEquals(100.0, vscA.getTargetP(), 0.0);
        assertEquals(500.0, vscA.getTargetVdc(), 0.0);
        assertEquals(10.0, vscA.getReactivePowerSetpoint(), 0.0);
        assertEquals(400.0, vscA.getVoltageSetpoint(), 0.0);
        assertFalse(vscA.isVoltageRegulatorOn());
        // change values in s4
        vscA.setControlMode(AcDcConverter.ControlMode.V_DC);
        vscA.setTargetP(-50.);
        vscA.setTargetVdc(495.);
        vscA.setReactivePowerSetpoint(20.0);
        vscA.setVoltageSetpoint(405.0);
        vscA.setVoltageRegulatorOn(true);

        // remove s2
        variantManager.removeVariant("s2");

        variantManager.cloneVariant("s4", "s2b");
        variantManager.setWorkingVariant("s2b");
        // check values cloned by allocate
        assertEquals(AcDcConverter.ControlMode.V_DC, vscA.getControlMode());
        assertEquals(-50., vscA.getTargetP(), 0.0);
        assertEquals(495., vscA.getTargetVdc(), 0.0);
        assertEquals(20.0, vscA.getReactivePowerSetpoint(), 0.0);
        assertEquals(405.0, vscA.getVoltageSetpoint(), 0.0);
        assertTrue(vscA.isVoltageRegulatorOn());

        // recheck initial variant value
        variantManager.setWorkingVariant(VariantManagerConstants.INITIAL_VARIANT_ID);
        assertEquals(AcDcConverter.ControlMode.P_PCC, vscA.getControlMode());
        assertEquals(100.0, vscA.getTargetP(), 0.0);
        assertEquals(500.0, vscA.getTargetVdc(), 0.0);
        assertEquals(10.0, vscA.getReactivePowerSetpoint(), 0.0);
        assertEquals(400.0, vscA.getVoltageSetpoint(), 0.0);
        assertFalse(vscA.isVoltageRegulatorOn());

        // remove working variant s4
        variantManager.setWorkingVariant("s4");
        variantManager.removeVariant("s4");
        assertThrows(PowsyblException.class, vscA::getControlMode, "Variant index not set");
        assertThrows(PowsyblException.class, vscA::getTargetP, "Variant index not set");
        assertThrows(PowsyblException.class, vscA::getTargetVdc, "Variant index not set");
        assertThrows(PowsyblException.class, vscA::getReactivePowerSetpoint, "Variant index not set");
        assertThrows(PowsyblException.class, vscA::getVoltageSetpoint, "Variant index not set");
        assertThrows(PowsyblException.class, vscA::isVoltageRegulatorOn, "Variant index not set");
    }
}