gatherDataToConvertFrom(Network network);
+
+ /**
+ * Create new name for ipso component with one connection.
+ * Example: C000002 (where 'C' is a prefix)
+ * The prefix of the name is given from {@link ComponentType }
+ * @return unique name
+ * @see ComponentType
+ */
+ String createIpsoId();
+
+ /**
+ * Create new name for two side connectable ipso component
+ * The new name is composeb by name1-name2-x
+ * with x as parrallele index
+ * @param nodeName1
+ * @param nodeName2
+ * @return unique name
+ */
+ String createIdFrom(String nodeName1, String nodeName2);
+
+ /**
+ * @return the conversion context
+ */
+ ConversionContext getContext();
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/NetworkModelConverter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/NetworkModelConverter.java
new file mode 100644
index 00000000..0c3db666
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/NetworkModelConverter.java
@@ -0,0 +1,66 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.converter;
+
+import eu.itesla_project.cta.model.*;
+import eu.itesla_project.iidm.network.*;
+
+import java.util.List;
+/**
+ * @author Yannick Pihan
+ */
+public class NetworkModelConverter {
+
+ /**
+ * constructor
+ */
+ public NetworkModelConverter() {
+ }
+
+ /**
+ * @return Ipso Network State from Iidm Network
+ */
+ public IpsoNetworkState convert(Network network, ConversionContext context) {
+
+ // create ipso network model
+ IpsoNetworkState ipsoNetwork = new IpsoNetworkState(0, context.getCaseName(), context.getMappingBetweenIidmIdAndIpsoEquipment());
+
+ ModelConverter nodeConverter = new NodeModelConverter(context);
+ List acNodes = nodeConverter.convert(network);
+
+ ModelConverter xNodeConverter = new XnodeModelConverter(context);
+ acNodes.addAll(xNodeConverter.convert(network));
+ ipsoNetwork.addNodes(acNodes);
+
+ ModelConverter lineConverter = new LineModelConverter(context);
+ List acLines = lineConverter.convert(network);
+ ipsoNetwork.addLines(acLines);
+
+ ModelConverter danglingLineConverter = new DanglingLineModelConverter(context);
+ ipsoNetwork.addLines(danglingLineConverter.convert(network));
+
+ ModelConverter generatorConverter = new GeneratorConverter(context);
+ ipsoNetwork.addGenerators(generatorConverter.convert(network));
+
+ ModelConverter loadConverter = new LoadModelConverter(context);
+ ipsoNetwork.addLoads(loadConverter.convert(network));
+
+ ModelConverter xLoadModelConverter = new XloadModelConverter(context);
+ ipsoNetwork.addLoads(xLoadModelConverter.convert(network));
+
+ ModelConverter bankConverter = new BankModelConverter(context);
+ ipsoNetwork.addBanks(bankConverter.convert(network));
+
+ ModelConverter couplingConverter = new CouplingDeviceModelConverter(context);
+ ipsoNetwork.addCouplings(couplingConverter.convert(network));
+
+ ModelConverter
+ transformerConverter = new TwoWindingsTransformerModelConverter(context);
+ ipsoNetwork.addTwoWindingsTransformers(transformerConverter.convert(network));
+
+ return ipsoNetwork;
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/NodeModelConverter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/NodeModelConverter.java
new file mode 100644
index 00000000..df322395
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/NodeModelConverter.java
@@ -0,0 +1,160 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.converter;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import com.google.gdata.util.common.base.Pair;
+import eu.itesla_project.cta.model.IpsoNode;
+import eu.itesla_project.cta.model.IpsoNodeType;
+import eu.itesla_project.cta.model.IpsoRegionType;
+import eu.itesla_project.iidm.network.Bus;
+import eu.itesla_project.iidm.network.Network;
+import eu.itesla_project.iidm.network.util.Identifiables;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * @author Yannick Pihan
+ */
+class NodeModelConverter extends AbstractNodeModelConverter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NodeModelConverter.class);
+
+ public NodeModelConverter(ConversionContext context) {
+ super(context);
+ }
+
+ /**
+ * Convert iidm bus to ipso node .
+ * Moreover, the conversion performs the research of
+ * macro region as internal or external and de type PV, SB or PQ for nodes
+ *
+ * @param network
+ * @return list of node for ipso
+ */
+ @Override
+ public List convert(Network network) {
+ Preconditions.checkArgument(network != null, "network cannto be null");
+ List nodes = new ArrayList<>();
+
+ SpecialNodeFinder specialNodesFinder = new SpecialNodeFinder();
+ for(Bus bus : Identifiables.sort(gatherDataToConvertFrom(network)) ) {
+ // check if the node is special
+ specialNodesFinder.browse(bus);
+ // createAmplModelFrom it to Ipso node
+ final IpsoNode ipsoNode = this.doConvert(bus);
+ // store created ipso node
+ nodes.add(ipsoNode);
+ // add bus and node names to the dictionary
+ super.addToDictionary(bus, ipsoNode);
+ }
+
+ // set PV node type
+ definePvNodesFor(nodes, specialNodesFinder);
+
+ // set slackbus type
+ if (specialNodesFinder.hasSlackBusFound() ) {
+ defineSlackBusfor(nodes, specialNodesFinder);
+ }
+ else {
+ LOG.error("no slackbus found!");
+ }
+
+ // set Macro region internal or external
+ defineMacroRegionOf(nodes);
+
+ return nodes;
+ }
+
+ @Override
+ protected ComponentType getComponentType() {
+ return ComponentType.NODE;
+ }
+
+ @Override
+ public Iterable gatherDataToConvertFrom(Network network) {
+ return network.getBusBreakerView().getBuses();
+ }
+
+ @Override
+ protected IpsoNode doConvert(Bus bus) {
+ return super.convertBus(bus.getId(), bus);
+ }
+
+ /**
+ * Change node type to slackbus in the list of Ipso nodes
+ * @param nodes
+ * @param specialNodeFinder
+ */
+ private void defineSlackBusfor(List nodes, SpecialNodeFinder specialNodeFinder) {
+ int index = specialNodeFinder.getSlackBusIndex();
+ IpsoNode ipsoNode = nodes.get(index);
+ // set the type of node to SB
+ ipsoNode.setNodeType(IpsoNodeType.SB);
+ nodes.set(index ,ipsoNode);
+ }
+
+ private void definePvNodesFor(List nodes, SpecialNodeFinder specialNodeFinder) {
+ for(int index : specialNodeFinder.getPvNodeIndexes()) {
+ IpsoNode ipsoNode = nodes.get(index);
+ if (!ipsoNode.isSlackBus()) {
+ // set the type of node to PV
+ ipsoNode.setNodeType(IpsoNodeType.PV);
+ // TODO à confirmer
+ //ipsoNode.setValue(NodeAttribute.ACTIVE_POWER, specialNodeFinder.getSlackBusGenerator().getTargetP() );
+ nodes.set(index, ipsoNode);
+ }
+ }
+ }
+
+ /**
+ * Defines the macroregion of node as internal or external accordingly to
+ * the number of node by region. The bigger number of nodes for a given region
+ * will be set as "Internal", others as "External"
+ * @param nodes
+ */
+ private void defineMacroRegionOf(List nodes) {
+ Preconditions.checkArgument(!nodes.isEmpty(), "At least one node is required.");
+
+ defineEveryNodeAsExternal(nodes);
+ // order IpsoNode by Country
+ Multimap nodesByCountry = Multimaps.index(nodes, byCountry());
+ String internalCountry = findCountryThatContainsTheBiggestNumberOfNodes(nodesByCountry);
+
+ // internal nodes
+ for (IpsoNode node : nodesByCountry.get(internalCountry)) {
+ node.setMacroRegionName(IpsoRegionType.INTERNAL.getValue());
+ }
+ }
+
+ private Function byCountry() {
+ return input -> input.getRegionName();
+ }
+
+ private String findCountryThatContainsTheBiggestNumberOfNodes(Multimap nodeByCountry) {
+ Pair maxLengthWithCountry = null;
+ for (String country : nodeByCountry.keySet()) {
+ int numberOfNodes = nodeByCountry.get(country).size();
+ if (maxLengthWithCountry == null || maxLengthWithCountry.getSecond() < numberOfNodes) {
+ maxLengthWithCountry = Pair.of(country, numberOfNodes);
+ }
+ }
+ return maxLengthWithCountry.getFirst();
+ }
+
+ private void defineEveryNodeAsExternal(List nodes) {
+ // default values
+ for (IpsoNode node : nodes) {
+ node.setMacroRegionName(IpsoRegionType.EXTERNAL.getValue());
+ }
+ }
+
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/SpecialNodeFinder.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/SpecialNodeFinder.java
new file mode 100644
index 00000000..c02ddbf4
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/SpecialNodeFinder.java
@@ -0,0 +1,142 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.converter;
+
+import eu.itesla_project.iidm.network.Bus;
+import eu.itesla_project.iidm.network.Equipments;
+import eu.itesla_project.iidm.network.Generator;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+/**
+ * @author Yannick Pihan
+ */
+final class SpecialNodeFinder {
+
+ private Bus slackBus;
+ private Generator slackBusGenerator;
+ private int slackBusIndex;
+ private int busCounter;
+ private Set pvNodeIndexes;
+
+ /**
+ * constructor
+ */
+ public SpecialNodeFinder() {
+ resetFinder();
+ }
+
+ /**
+ * Reinitialize finder
+ */
+ public void resetFinder() {
+ slackBus = null;
+ slackBusGenerator = null;
+ slackBusIndex = -1;
+ busCounter = 0;
+ pvNodeIndexes = new HashSet<>();
+ }
+
+ /**
+ * Browses and determines the bus which is slackbus or PV node
+ */
+ public void browse(Bus bus) {
+
+ if (atLeastOneGeneratorFor(bus)) {
+
+ for (Generator generator : bus.getGenerators()) {
+
+ // a regulated generator
+ if (generator.isVoltageRegulatorOn()) {
+
+ if (areConnected(generator, bus))
+ {
+ storeBiggest(generator, bus);
+
+ storePvNodesFor(generator);
+ }
+ }
+ }
+ }
+ busCounter++;
+ }
+
+ private boolean atLeastOneGeneratorFor(Bus bus) {
+ return bus.getGenerators() != null;
+ }
+
+ private boolean areConnected(Generator generator, Bus CandidateBus) {
+ Equipments.ConnectionInfo info = Equipments.getConnectionInfoInBusBreakerView(generator.getTerminal());
+ // if the generator is connected to the bus
+ if (info.isConnected() ) {
+ //...Assure the candidate bus is the real bus and not an aggregated bus
+ return info.getConnectionBus().getId().equals(CandidateBus.getId());
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * get index of slackbus among all browsed buses
+ * @return
+ */
+ public int getSlackBusIndex() {
+ return slackBusIndex;
+ }
+
+ public boolean hasSlackBusFound() {
+ return slackBusIndex >= 0;
+ }
+
+ /**
+ * get the slackbus chosen among all browsed buses
+ * @return
+ */
+ public Bus getSlackBus() {
+ return slackBus;
+ }
+
+ /**
+ *
+ * @return the bigger generator connected to the slackbus
+ */
+ public Generator getSlackBusGenerator() {
+ return slackBusGenerator;
+ }
+
+ /**
+ * Get PV node indexes among all browsed buses
+ * @return
+ */
+ public Set getPvNodeIndexes() {
+ return Collections.unmodifiableSet(pvNodeIndexes);
+ }
+
+ /**
+ * Store biggest generator (Pmax) and his connection bus as slackbus
+ */
+ private void storeBiggest(Generator generator, Bus bus) {
+ if (slackBusGenerator == null || isBiggestGenerator(generator)) {
+ slackBus = bus;
+ slackBusGenerator = generator;
+ slackBusIndex = this.busCounter;
+ }
+ }
+
+ private boolean isBiggestGenerator(Generator generator) {
+ return generator.getMaxP() > slackBusGenerator.getMaxP();
+ }
+
+ private void storePvNodesFor(Generator generator) {
+
+ // at least on regulator in V Regulator is enough
+ // to define the connected node as PV
+ if (generator.isVoltageRegulatorOn()) {
+ pvNodeIndexes.add(this.busCounter);
+ }
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/TwoWindingsTransformerModelConverter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/TwoWindingsTransformerModelConverter.java
new file mode 100644
index 00000000..a8675aa5
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/TwoWindingsTransformerModelConverter.java
@@ -0,0 +1,314 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.converter;
+
+import eu.itesla_project.commons.ITeslaException;
+import eu.itesla_project.cta.model.*;
+import eu.itesla_project.iidm.network.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+import java.util.function.Function;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Optional.ofNullable;
+/**
+ * @author Yannick Pihan
+ */
+class TwoWindingsTransformerModelConverter extends AbstractBranchModelConverter{
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(TwoWindingsTransformerModelConverter.class);
+ protected static final String CANNOT_FIND_REGULATED_BUS = "Cannot find regulated bus for TwoWindingTransformer having the id: ";
+ protected static final String PHASE_TRANSFORMER_WITH_UNCONSISTENT_REGULATION_BUS = "Phase transformer %s has a regulated bus which is different of bus1 and bus2";
+ protected static final String TRANSFORMER_HAS_TO_MANY_REGULATION_MODE = "Ratio transformer %s with 2 regulation modes is not supported";
+
+
+ final class Losses {
+ float cu;
+ float fe;
+ float magnetizingCurrent;
+ float saturation_exponent;
+ }
+
+
+ final class IpsoStep {
+ float rho, alpha;
+ TransformerRegulationType mode;
+ float un01, un02, ucc, phase;
+ }
+
+ /**
+ * Constructor
+ * @param context
+ */
+ TwoWindingsTransformerModelConverter(ConversionContext context) {
+ super(context);
+ }
+
+ @Override
+ protected IpsoTwoWindingsTransformer doConvert(TwoWindingsTransformer transformer) {
+
+ Equipments.ConnectionInfo info1 = Equipments.getConnectionInfoInBusBreakerView(transformer.getTerminal1());
+ Equipments.ConnectionInfo info2 = Equipments.getConnectionInfoInBusBreakerView(transformer.getTerminal2());
+ Bus bus1 = info1.getConnectionBus();
+ Bus bus2 = info2.getConnectionBus();
+ final IpsoNode ipsoNode1 = getContext().getMappingBetweenIidmIdAndIpsoEquipment().getIpsoNodeFor(bus1).get();
+ final IpsoNode ipsoNode2 = getContext().getMappingBetweenIidmIdAndIpsoEquipment().getIpsoNodeFor(bus2).get();
+
+ String id = createIdFrom(ipsoNode1.getId(), ipsoNode2.getId());
+
+ Losses losses = this.computeLosses(transformer);
+ IpsoTap tap = this.computeTapChangerInfo(transformer);
+ Map steps = computeIpsoSteps(transformer, tap);
+
+ final TransformerRegulationParameters regulationParameters = findRegulationParametersFor(transformer, bus1, bus2);
+
+ //...writeVariables records
+ List indexes = new ArrayList<>();
+ List voltages_side1 = new ArrayList<>();
+ List voltages_side2 = new ArrayList<>();
+ List phases = new ArrayList<>();
+ List uccs = new ArrayList<>();
+ if (steps.size() > 0) {
+
+ for (int index : steps.keySet()) {
+ IpsoStep step = steps.get(index);
+ indexes.add(index);
+ voltages_side1.add(step.un01);
+ voltages_side2.add(step.un02);
+ phases.add(step.phase);
+ uccs.add(step.ucc);
+ }
+ }
+
+ return new IpsoTwoWindingsTransformer(
+ id,
+ transformer.getId(),
+ ipsoNode1,
+ ipsoNode2,
+ info1.isConnected(),
+ info2.isConnected(),
+ losses.cu,
+ losses.fe,
+ losses.magnetizingCurrent,
+ losses.saturation_exponent,
+ rate(),
+ tap.getNominal(),
+ tap.getInitial(),
+ tap.getLowstep(),
+ tap.getHighstep(),
+ steps.size(),
+ indexes,
+ voltages_side1,
+ voltages_side2,
+ phases,
+ uccs,
+ findMaxCurrentPermanentLimitFor(transformer),
+ findCurrentFlow(transformer, regulationParameters.getRegulationType()),
+ regulationParameters,
+ getContext().getWorld());
+ }
+
+ private float findCurrentFlow(TwoWindingsTransformer transformer, TransformerRegulationType transformerRegulationType) {
+ checkArgument(transformer.getTerminal1() != null, "transformer.getTerminal1() must not be null");
+ checkArgument(transformer.getTerminal2() != null, "transformer.getTerminal2() must not be null");
+ float flow1 = DataUtil.getSafeValueOf(transformer.getTerminal1().getI(), 0);
+ float flow2 = DataUtil.getSafeValueOf(transformer.getTerminal2().getI(), 0);
+ return Math.max(flow1, flow2);
+ }
+
+ private Function getSafeI() {
+ return terminal -> DataUtil.getSafeValueOf(terminal.getI());
+ }
+
+ private Losses computeLosses(TwoWindingsTransformer transformer) {
+ Losses losses = new Losses();
+
+ float ratedU1 = transformer.getRatedU1();
+ float ratedU2 = transformer.getRatedU2();
+ float nominalU2 = transformer.getTerminal2().getVoltageLevel().getNominalV();
+
+ //...mTrans.getR() = Get the nominal series resistance specified in Ω at the secondary voltage side.
+ float Rpu2 = ( transformer.getR() * snref() ) / nominalU2 / nominalU2; //...total line resistance [p.u.](Base snref)
+ float Gpu2 = ( transformer.getG() / snref() ) * nominalU2 * nominalU2; //...semi shunt conductance [p.u.](Base snref)
+ float Bpu2 = ( transformer.getB() / snref() ) * nominalU2 * nominalU2; //...semi shunt susceptance [p.u.](Base snref)
+
+ //...changing base snref -> base RATE to compute losses
+ losses.cu = Rpu2 * rate() * 100f / snref(); //...base RATE (100F -> %)
+ losses.fe = 10000f * ( Gpu2 / rate()) * (snref() / 100f) ; //...base RATE
+ float modgb = (float) Math.sqrt(Math.pow(Gpu2,2.f) + Math.pow(Bpu2, 2.f) );
+ losses.magnetizingCurrent = 10000 * ( modgb / rate()) * (snref() / 100f); //...magnetizing current [% base RATE]
+ losses.saturation_exponent = 1.f;
+
+ return losses;
+ }
+
+ private IpsoTap computeTapChangerInfo(TwoWindingsTransformer transformer) {
+ if (transformer.getRatioTapChanger() != null) {
+ return new IpsoTap(transformer.getRatioTapChanger());
+ } else if (transformer.getPhaseTapChanger() != null) {
+ return new IpsoTap(transformer.getPhaseTapChanger());
+ } else {
+ return new IpsoTap();
+ }
+ }
+
+ private TransformerRegulationParameters findRegulationParametersFor(TwoWindingsTransformer transformer, Bus bus1, Bus bus2) {
+ checkArgument(transformer != null, "transformer must not be null");
+ checkArgument(bus1 != null, "bus1 must not be null");
+ checkArgument(bus2 != null, "bus2 must not be null");
+ //...get tap changers
+ RatioTapChanger rtc = transformer.getRatioTapChanger();
+ PhaseTapChanger ptc = transformer.getPhaseTapChanger();
+
+ TransformerRegulationType regulationType = TransformerRegulationType.NO;
+ float setpoint = 0.f;
+ Bus regulatedbus = null; // get bus1 as regulated bus by default
+ IpsoNode ipsoRegulatedBus = null;
+ int currentStepPosition = 0;
+
+ // Ratio tap changer (voltage regulating)
+ if (isRegulationDefinedFor(rtc)) {
+ regulatedbus = findRegulatedBusFor(rtc).get();
+
+ regulationType = findVolategRegulationType(bus1, bus2, regulatedbus)
+ .orElseThrow(() -> new IllegalStateException(unconsistentRegulationBusFor(transformer)));
+
+ setpoint = rtc.getTargetV() / regulatedbus.getVoltageLevel().getNominalV(); // !!! in PU
+ currentStepPosition = rtc.getTapPosition();
+ }
+
+ // Phase tap changer (active power regulating)
+ if (isRegulationDefinedFor(ptc)) {
+ // two regulation types cannot be defined on the same twoWindingTransformer
+ if (regulationType.isVoltageRegulationType()) {
+ throw new ITeslaException(String.format(TRANSFORMER_HAS_TO_MANY_REGULATION_MODE, transformer.getId()));
+ }
+ setpoint = ptc.getThresholdI(); // in Ampere
+ regulatedbus = findRegulatedBusFor(ptc).get();
+ currentStepPosition = ptc.getTapPosition();
+ regulationType = findFlowRegulationType(bus1, bus2, regulatedbus)
+ .orElseThrow(() -> new IllegalStateException(unconsistentRegulationBusFor(transformer)));
+ }
+
+ if (regulationType != TransformerRegulationType.NO ) {
+ ipsoRegulatedBus = getContext().getMappingBetweenIidmIdAndIpsoEquipment().getIpsoNodeFor(regulatedbus).get();
+ }
+ return new TransformerRegulationParameters(regulationType, setpoint, regulationType.getSideValue(), currentStepPosition, ipsoRegulatedBus);
+ }
+
+ private String unconsistentRegulationBusFor(TwoWindingsTransformer transformer) {
+ return String.format(PHASE_TRANSFORMER_WITH_UNCONSISTENT_REGULATION_BUS, transformer.getId());
+ }
+
+ private Optional findRegulatedBusFor(TapChanger tapChanger) {
+ checkArgument(tapChanger != null, "tap changer must not be null.");
+ return ofNullable(tapChanger.getTerminal())
+ .map(Terminal::getBusBreakerView)
+ .map(Terminal.BusBreakerView::getBus);
+ }
+
+ private Optional findVolategRegulationType(Bus bus1, Bus bus2, Bus regulatedbus) {
+ checkArgument(bus1 != null, "bus1 must not be null");
+ checkArgument(bus2 != null, "bus1 must not be null");
+ checkArgument(regulatedbus != null, "regulatedbus must not be null");
+ if (bus1.equals(regulatedbus)) {
+ return Optional.of(TransformerRegulationType.VOLTAGE_SIDE_1);
+ } else if (bus2.equals(regulatedbus)) {
+ return Optional.of(TransformerRegulationType.VOLTAGE_SIDE_2);
+ }
+ else {
+ return Optional.empty();
+ }
+ }
+
+ private Optional findFlowRegulationType(Bus bus1, Bus bus2, Bus regulatedbus) {
+ checkArgument(bus1 != null, "bus1 must not be null");
+ checkArgument(bus2 != null, "bus1 must not be null");
+ checkArgument(regulatedbus != null, "regulatedbus must not be null");
+ if (bus1.equals(regulatedbus)) {
+ return Optional.of(TransformerRegulationType.ACTIVE_FLUX_1);
+ } else if (bus2.equals(regulatedbus)) {
+ return Optional.of(TransformerRegulationType.ACTIVE_FLUX_2);
+ }
+ else {
+ return Optional.empty();
+ }
+ }
+
+ private boolean isRegulationDefinedFor(TapChanger tapChanger) {
+ return tapChanger != null && tapChanger.isRegulating() && findRegulatedBusFor(tapChanger).isPresent();
+ }
+
+ private Map computeIpsoSteps(TwoWindingsTransformer transformer, IpsoTap tap) {
+
+ float ratedU1 = transformer.getRatedU1();
+ float ratedU2 = transformer.getRatedU2();
+ float nomiU2 = transformer.getTerminal2().getVoltageLevel().getNominalV();
+
+ //...getValue ratio tap changer
+ RatioTapChanger rtc = transformer.getRatioTapChanger();
+ PhaseTapChanger ptc = transformer.getPhaseTapChanger();
+
+ Map steps = new TreeMap<>();
+ for ( int s = tap.getLowstep() ; s <= tap.getHighstep() ; s++ ) {
+
+ IpsoStep step = new IpsoStep();
+ step.un01 = ratedU1;
+ step.un02 = ratedU2;
+
+ float dr = 0f, dx = 0f, ucc, phase = 0f;
+ if (rtc != null ) {
+ step.rho = rtc.getStep(s).getRho();
+ step.un01 /= rtc.getStep(s).getRho() ;
+ step.un02 = ratedU2;
+ dr += rtc.getStep(s).getR();
+ dx += rtc.getStep(s).getX();
+ }
+
+ if (ptc != null ) {
+ step.alpha = ptc.getStep(s).getAlpha();
+ phase = ptc.getStep(s).getAlpha();
+ step.un01 /= ptc.getStep(s).getRho(); //temporary, to be investigated for ptc
+ dr += ptc.getStep(s).getR();
+ dx += ptc.getStep(s).getX();
+ }
+
+ //...transformer.getR() = Get the nominal series resistance specified in Ω at the secondary voltage side.
+ float rpu2 = ( transformer.getR() * (1 + dr/100.0f) * snref() ) / nomiU2 / nomiU2; //...total line resistance [p.u.](Base snref)
+ float xpu2 = ( transformer.getX() * (1 + dx/100.0f) * snref() ) / nomiU2 / nomiU2; //...total line reactance [p.u.](Base snref)
+
+ //...leakage impedance [%] (base RATE)
+ if ( xpu2 < 0 ) {
+ ucc = xpu2 * rate() * 100f / snref();
+ }
+ else
+ {
+ float modrx = (float) Math.sqrt(Math.pow(rpu2,2.f) + Math.pow(xpu2, 2.f) );
+ ucc = modrx * rate() * 100f / snref();
+ }
+
+ step.ucc = ucc;
+ step.phase = phase;
+ steps.put(s, step);
+ }
+
+ return steps;
+
+ }
+
+ @Override
+ public Iterable gatherDataToConvertFrom(Network network) {
+ return network.getTwoWindingsTransformers();
+ }
+
+ @Override
+ protected ComponentType getComponentType() {
+ return ComponentType.TWO_WINDINGS_TRANSFORMER;
+ }
+
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/XloadModelConverter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/XloadModelConverter.java
new file mode 100644
index 00000000..7ec80596
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/XloadModelConverter.java
@@ -0,0 +1,69 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.converter;
+
+import eu.itesla_project.cta.model.IpsoLoad;
+import eu.itesla_project.cta.model.IpsoNode;
+import eu.itesla_project.iidm.network.DanglingLine;
+import eu.itesla_project.iidm.network.Network;
+
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
+/**
+ * @author Yannick Pihan
+ */
+class XloadModelConverter extends AbstractLoadModelConverter{
+
+ XloadModelConverter(ConversionContext context) {
+ super(context);
+ }
+
+
+ @Override
+ public IpsoLoad doConvert(DanglingLine danglingLine) {
+ checkArgument(danglingLine != null, "danglingLine must not be null");
+
+ String id = createIpsoId();
+ Optional ipsoNodeFor = getContext().getMappingBetweenIidmIdAndIpsoEquipment().getIpsoNodeFor(IpsoConverterUtil.getFictiveBusIdFor(danglingLine));
+
+ if(ipsoNodeFor.isPresent()) {
+ IpsoNode ipsoNode = ipsoNodeFor.get();
+
+ float activePower = danglingLine.getP0();
+ float reactivePower = danglingLine.getQ0();
+ return new IpsoLoad(
+ id,
+ getIdOf(danglingLine),
+ ipsoNode,
+ true,
+ activePower,
+ reactivePower,
+ getContext().getWorld());
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Override
+ public Iterable gatherDataToConvertFrom(Network network) {
+ return network.getDanglingLines();
+ }
+
+ @Override
+ protected ComponentType getComponentType() {
+ return ComponentType.XLOAD;
+ }
+
+ /**
+ * @return A fake id for fictive node created from danglingLine
+ */
+ @Override
+ protected String getIdOf(DanglingLine danglingLine) {
+ return IpsoConverterUtil.getFictiveLoadIdFor(danglingLine);
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/XnodeModelConverter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/XnodeModelConverter.java
new file mode 100644
index 00000000..c97ebf63
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/converter/XnodeModelConverter.java
@@ -0,0 +1,88 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.converter;
+
+import eu.itesla_project.cta.model.IpsoNode;
+import eu.itesla_project.cta.model.IpsoNodeType;
+import eu.itesla_project.cta.model.IpsoRegionType;
+import eu.itesla_project.iidm.network.Bus;
+import eu.itesla_project.iidm.network.DanglingLine;
+import eu.itesla_project.iidm.network.Network;
+import eu.itesla_project.iidm.network.util.SV;
+
+import static com.google.common.base.Preconditions.checkArgument;
+/**
+ * @author Yannick Pihan
+ */
+class XnodeModelConverter extends AbstractNodeModelConverter {
+
+ public XnodeModelConverter(ConversionContext context) {
+ super(context);
+ }
+
+ @Override
+ public IpsoNode doConvert(DanglingLine danglingLine) {
+ checkArgument(danglingLine != null, "danglingLine must not be null");
+ checkArgument(danglingLine.getTerminal() != null, "danglingLine.getTerminal() must not be null");
+ checkArgument(danglingLine.getTerminal().getBusBreakerView() != null, "danglingLine.getTerminal().getBusBreakerView() must not be null");
+
+ //checkArgument(danglingLine.getTerminal().getBusBreakerView().getBus()!= null, "danglingLine.getTerminal().getBusBreakerView().getBus() must not be null");
+ if (danglingLine.getTerminal().getBusBreakerView().getBus() == null) {
+ return null;
+ } else {
+ final String id = createIpsoId();
+ final Bus bus = danglingLine.getTerminal().getBusBreakerView().getBus();
+
+ // voltage of known bus of the dangling line
+ final float voltage = bus.getV();
+ // angle of known bus of the dangling line
+ final float angle = bus.getAngle();
+
+ final float p = danglingLine.getTerminal().getP();
+ final float q = danglingLine.getTerminal().getQ();
+
+ final float pn = danglingLine.getTerminal().getBusBreakerView().getBus().getP();
+ final float qn = danglingLine.getTerminal().getBusBreakerView().getBus().getQ();
+
+ final SV known = new SV(p, q, voltage, angle);
+ final SV fictitious = known.otherSide(danglingLine);
+ final float baseVoltage = findBaseVoltage(bus);
+
+ return new IpsoNode(
+ id,
+ getIdOf(danglingLine),
+ findAreaFor(bus),
+ IpsoRegionType.EXTERNAL.getValue(),
+ baseVoltage,
+ fictitious.getU(),
+ fictitious.getA(),
+ IpsoNodeType.PQ,
+ fictitious.getP(),
+ fictitious.getQ(),
+ findLowVoltageLevel(bus, baseVoltage),
+ findHighVoltageLevel(bus, baseVoltage),
+ getContext().getWorld());
+ }
+ }
+
+ @Override
+ public Iterable gatherDataToConvertFrom(Network network) {
+ return network.getDanglingLines();
+ }
+
+ @Override
+ protected ComponentType getComponentType() {
+ return ComponentType.XNODE;
+ }
+
+ /**
+ * @return A fake id for fictive node created from danglingLine
+ */
+ @Override
+ protected String getIdOf(DanglingLine danglingLine) {
+ return IpsoConverterUtil.getFictiveBusIdFor(danglingLine);
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplModelWriter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplModelWriter.java
new file mode 100644
index 00000000..c2a09b19
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplModelWriter.java
@@ -0,0 +1,45 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.io;
+
+import eu.itesla_project.cta.model.AmplModel;
+import eu.itesla_project.cta.service.AmplConstants;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeConstants;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.toMap;
+/**
+ * @author Yannick Pihan
+ */
+public class AmplModelWriter {
+
+ public void write(AmplModel model, String toPath, String templatePath) throws IOException {
+ VelocityEngine templateEngine = new VelocityEngine();
+ templateEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, templatePath);
+ templateEngine.init();
+ Template template = templateEngine.getTemplate(AmplConstants.TEMPLATE_FILE);
+
+ VelocityContext context = new VelocityContext(formatParameters(model));
+ FileWriter writer = new FileWriter(new File(toPath));
+ template.merge(context, writer);
+
+ writer.close();
+ }
+
+ private Map> formatParameters(AmplModel model) {
+ return stream(AmplParameters.values())
+ .collect(toMap(AmplParameters::getName, parameter -> parameter.format(model)));
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplParameterFormatter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplParameterFormatter.java
new file mode 100644
index 00000000..6b2f4c31
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplParameterFormatter.java
@@ -0,0 +1,46 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.io;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.stream.Collectors.joining;
+/**
+ * Copyright (c) 2016, Tractebel (http://www.itesla-project.eu/consortium)
+ * 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/.
+ *
+ * @author Yannick Pihan
+ */
+class AmplParameterFormatter {
+
+ private static final String DELIMITER = "\t";
+
+ public String format(List> list) {
+ checkArgument(list != null, "list must not be null");
+ return list.stream()
+ .map(e -> convertBooleanToInteger(e))
+ .map(Object::toString)
+ .collect(joining(DELIMITER));
+ }
+
+ private Object convertBooleanToInteger(Object e) {
+ if(e instanceof Boolean ) {
+ return (boolean)e ? 1 : 0;
+ }
+ else if(e instanceof Float && (float)e == Float.NEGATIVE_INFINITY) {
+ return "-Infinity";
+ }
+ else if(e instanceof Float && (float)e == Float.POSITIVE_INFINITY) {
+ return "Infinity";
+ }
+ else {
+ return e;
+ }
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplParameters.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplParameters.java
new file mode 100644
index 00000000..82061437
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/AmplParameters.java
@@ -0,0 +1,65 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.io;
+
+import eu.itesla_project.cta.model.AmplModel;
+import eu.itesla_project.cta.model.AmplWritable;
+
+import java.util.List;
+import java.util.function.Function;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Lists.newArrayList;
+import static java.util.stream.Collectors.toList;
+/**
+ * @author Yannick Pihan
+ */
+public enum AmplParameters {
+
+ GENERATORS("generators", AmplModel::getGenerators),
+ LOADS("loads", AmplModel::getLoads),
+ CAPACITORS("capacitors", AmplModel::getCapacitors),
+ NODES("nodes", AmplModel::getNodes),
+ TRANSFORMERS("transformers", AmplModel::getTransBranches),
+ SIMPLE_BRANCHES("simpleBranches", AmplModel::getSimpleBranches),
+ COUPLAGES("couplages", AmplModel::getCouplages),
+ SLACKBUSES("slackbuses", AmplModel::getSlackBuses),
+
+ NODE_PARAMETERS("nodeParametersList", AmplModel::getNodeParameters),
+ SLACKBUS_PARAMETERS("slackbusParametersList", AmplModel::getSlackBusParameters),
+ GENERATOR_PARAMETERS("generatorParametersList", AmplModel::getGeneratorParameters),
+ LOAD_PARAMETERS("loadParametersList", AmplModel::getLoadParameters),
+ CAPACITOR_PARAMETERS("capacitorParametersList", AmplModel::getCapacitorParameters),
+ BRANCH_PARAMETERS("branchParametersList", AmplModel::getBranchParameters),
+ TRANSFORMER_PARAMETERS("transformerParametersList", AmplModel::getTransformerParameters),
+ COUPLING_PARAMETERS("couplingParametersList", AmplModel::getCouplingParameters),
+ ;
+
+ private static List EMPTY_SET = newArrayList("{}");
+ private static final AmplParameterFormatter FORMATTER = new AmplParameterFormatter();
+
+ private final String name;
+ private final Function> amplElements;
+
+ AmplParameters(String name,
+ Function> amplElements) {
+ this.name = name;
+ this.amplElements = amplElements;
+ }
+
+ public List format(AmplModel model) {
+ checkArgument(model != null, "model must not be null");
+ List strings = amplElements.apply(model)
+ .stream()
+ .map(element -> FORMATTER.format(element.getOrderedValues()))
+ .collect(toList());
+ return strings.isEmpty() ? EMPTY_SET : strings;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoCsvWriter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoCsvWriter.java
new file mode 100644
index 00000000..91cc5848
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoCsvWriter.java
@@ -0,0 +1,54 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.io;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import eu.itesla_project.cta.model.IpsoWritable;
+import org.supercsv.io.CsvListWriter;
+import org.supercsv.io.ICsvListWriter;
+import org.supercsv.prefs.CsvPreference;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.file.Path;
+import java.util.List;
+/**
+ * @author Yannick Pihan
+ */
+public class IpsoCsvWriter implements IpsoWriter {
+
+ @Override
+ public void write(List extends IpsoWritable> writables, Path toPath) throws IOException {
+ Preconditions.checkArgument(writables != null, "writables cannot be null");
+ Preconditions.checkArgument(toPath != null, "toPath cannot be null");
+
+ try (Writer writer = new FileWriter(toPath.toFile());
+ ICsvListWriter csvWriter = new CsvListWriter(writer, CsvPreference.EXCEL_PREFERENCE)) {
+ writeHeader(writables, csvWriter);
+ writeLines(writables, csvWriter);
+ }
+ }
+
+ private void writeLines(List extends IpsoWritable> writables, ICsvListWriter csvWriter) throws IOException {
+ for (IpsoWritable writable : writables) {
+ csvWriter.write(writable.getOrderedValues());
+ }
+ }
+
+ private void writeHeader(List extends IpsoWritable> writables, ICsvListWriter csvwriter) throws IOException {
+ IpsoWritable firstOne = Iterables.getFirst(writables, null);
+ if (firstOne != null) {
+ csvwriter.write(firstOne.getOrderedHeaders());
+ }
+ }
+
+ @Override
+ public IpsoOutputFormat getFormat() {
+ return IpsoOutputFormat.CSV;
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoOutputFormat.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoOutputFormat.java
new file mode 100644
index 00000000..1882cc4e
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoOutputFormat.java
@@ -0,0 +1,13 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.io;
+/**
+ * @author Yannick Pihan
+ */
+public enum IpsoOutputFormat {
+ CSV,
+ XML_SOAP
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoWriter.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoWriter.java
new file mode 100644
index 00000000..692135c1
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/IpsoWriter.java
@@ -0,0 +1,22 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.io;
+
+import eu.itesla_project.cta.model.IpsoWritable;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+/**
+ * @author Yannick Pihan
+ */
+public interface IpsoWriter {
+
+ void write(List extends IpsoWritable> writables, Path toPath) throws IOException;
+
+ IpsoOutputFormat getFormat();
+
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/io/Writers.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/Writers.java
new file mode 100644
index 00000000..2b53da30
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/io/Writers.java
@@ -0,0 +1,26 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.io;
+
+import java.util.ServiceLoader;
+/**
+ * @author Yannick Pihan
+ */
+public final class Writers {
+
+ private static final ServiceLoader WRITERS_LOADER = ServiceLoader.load(IpsoWriter.class);
+
+ private Writers() {}
+
+ public static IpsoWriter findWriterFor(IpsoOutputFormat format) {
+ for (IpsoWriter writer : WRITERS_LOADER) {
+ if (writer.getFormat() == format) {
+ return writer;
+ }
+ }
+ return null;
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractFlowConstraint.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractFlowConstraint.java
new file mode 100644
index 00000000..9a629463
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractFlowConstraint.java
@@ -0,0 +1,32 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.model;
+/**
+ * @author Yannick Pihan
+ */
+public abstract class AbstractFlowConstraint extends IpsoConstraint {
+
+ protected static final String FLOW_MIN = "FLOW_MIN";
+ protected static final String FLOW_MAX = "FLOW_MAX";
+ private final FlowUnit flowUnit;
+
+ public AbstractFlowConstraint(T equipment, FlowUnit flowUnit ,float min, float max, int world) {
+ super(equipment, min, max, world);
+ this.flowUnit = flowUnit;
+ }
+
+ public float getMaxFlow() {
+ return getBoundsMax();
+ }
+
+ public float getMinFlow() {
+ return getBoundsMin();
+ }
+
+ public FlowUnit getFlowUnit() {
+ return flowUnit;
+ }
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractIpsoBranch.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractIpsoBranch.java
new file mode 100644
index 00000000..a8dabf53
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractIpsoBranch.java
@@ -0,0 +1,42 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.model;
+
+import java.util.List;
+/**
+ * @author Yannick Pihan
+ */
+public abstract class AbstractIpsoBranch extends IpsoEquipment{
+
+ protected final IpsoNode ipsoNode1;
+ protected final IpsoNode ipsoNode2;
+
+ public AbstractIpsoBranch(String id, String iidmId, int world, IpsoNode ipsoNode1, IpsoNode ipsoNode2) {
+ super(id, iidmId, world);
+ this.ipsoNode1 = ipsoNode1;
+ this.ipsoNode2 = ipsoNode2;
+ }
+
+ public abstract boolean isConnected();
+
+ public boolean couldBeConnected(List topologicalActions) {
+ return this.isConnected() || topologicalActions.stream()
+ .filter(action -> action.getEquipmentId() == this.getId())
+ .anyMatch(action -> action.getSwitchAction().isOppositeTo(this.isConnected()));
+ }
+ protected char getConnectionCodeFor(boolean connected) {
+ return connected ? 'Y' : 'N';
+ }
+
+ public IpsoNode getIpsoNode2() {
+ return ipsoNode2;
+ }
+
+ public IpsoNode getIpsoNode1() {
+ return ipsoNode1;
+ }
+
+}
diff --git a/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractIpsoConstraintLineFlow.java b/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractIpsoConstraintLineFlow.java
new file mode 100644
index 00000000..cf035986
--- /dev/null
+++ b/cta-optimizer/src/main/java/eu/itesla_project/cta/model/AbstractIpsoConstraintLineFlow.java
@@ -0,0 +1,37 @@
+/** Copyright (c) 2016, Tractebel (http://www.tractebel-engie.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 eu.itesla_project.cta.model;
+
+import com.google.common.collect.Lists;
+
+import java.util.List;
+/**
+ * @author Yannick Pihan
+ */
+public abstract class AbstractIpsoConstraintLineFlow extends AbstractFlowConstraint {
+
+ public AbstractIpsoConstraintLineFlow(IpsoLine line, FlowUnit unit, float min, float max, int world) {
+ super(line, unit, min, max, world);
+ }
+
+ @Override
+ protected abstract float getConstrainedAttributeValueFor(IpsoLine equipment);
+
+ @Override
+ public List getOrderedHeaders() {
+ return Lists.newArrayList(
+ NAME,
+ UNIT,
+ FLOW_MIN,
+ FLOW_MAX,
+ WORLD);
+ }
+
+ @Override
+ public List