package holeg; import classes.AbstractCanvasObject; import classes.HolonObject; import classes.Node; import holeg.model.*; import holeg.power_flow.ComplexNumber; import holeg.simple_grid.SimpleGridBuilder; import holeg.simple_grid.SimpleGridEdge; import holeg.simple_grid.SimpleGridNode; import holeg.ui.PowerFlowAnalysisMenu; import holeg.ui.SolveResultMessageBox; import ui.controller.FlexManager; import ui.controller.SingletonControl; import ui.model.*; import java.util.*; import java.util.stream.Collectors; public class HolegGateway { private static Grid convert(MinimumNetwork network, int iteration, FlexManager flexManager) { SimpleGridBuilder gridBuilder = new SimpleGridBuilder(); HashMap canvasToGrid = new HashMap<>(); for (HolonObject object : network.getHolonObjectList()) { double power = object.getEnergyAtTimeStep(iteration); double reactivePower = object.getReactiveEnergyAtTimeStep(iteration); SimpleGridNode node; // Create house or generator if (power <= 0) node = gridBuilder.addHouse(new ComplexNumber(-power, reactivePower)); else node = gridBuilder.addGenerator(new ComplexNumber(power, reactivePower)); node.tag = object; // Find type by design if (object.getElements().stream().anyMatch(e -> e.getEleName().equalsIgnoreCase("SLACK"))) node.typeByDesign = NodeType.Slack; else if (object.getElements().stream().anyMatch(e -> e.getEleName().equalsIgnoreCase("TRANSFORMER"))) node.typeByDesign = NodeType.Transformer; else node.typeByDesign = NodeType.Bus; canvasToGrid.put(object, node); } // Add all switches and nodes for (AbstractCanvasObject object : network.getNodeAndSwitches()) { SimpleGridNode node = gridBuilder.addHouse(new ComplexNumber(0, 0)); node.tag = object; node.typeByDesign = NodeType.Bus; canvasToGrid.put(object, node); } // Add all cables for (IntermediateCableWithState cable : network.getEdgeList()) { SimpleGridNode a = canvasToGrid.get(cable.getModel().getA()); SimpleGridNode b = canvasToGrid.get(cable.getModel().getB()); if (a == null || b == null) continue; SimpleGridEdge edge = gridBuilder.connect(a, b, Math.max(1, cable.getModel().getRealLength())); edge.overrideImpedance = new ComplexNumber(cable.getModel().getOverrideResistance(), cable.getModel().getOverrideReactance()); edge.overrideShuntSusceptance = cable.getModel().getOverrideShuntSusceptance(); edge.tag = cable; } return gridBuilder.getGrid(); } private static void decorateNetwork(MinimumNetwork network, int iteration, FlexManager flexManager, DecoratedNetwork decoratedNetwork, Grid grid) { synchronized (decoratedNetwork.getLockObject()) { decoratedNetwork.clear(); // Convert all nodes for (GridNode node : grid.getNodes()) { SimpleGridNode simpleNode = (SimpleGridNode) node; // Create supplier, consumer or passiv object if (node.getPowerGeneration().lenSquared() > 0) decoratedNetwork.getSupplierList().add(new Supplier((HolonObject) simpleNode.tag, (float) node.getPowerGeneration().real, 0, simpleNode.voltage, simpleNode.phaseDegrees, simpleNode.typeSolved == NodeType.Slack)); else if (node.getPowerConsumption().lenSquared() > 0) decoratedNetwork.getConsumerList().add(new Consumer((HolonObject) simpleNode.tag, (float) node.getPowerConsumption().real, simpleNode.voltage, simpleNode.phaseDegrees, Math.cos(simpleNode.getPowerConsumption().angle()), simpleNode.typeSolved == NodeType.Slack)); else if (simpleNode.tag instanceof HolonObject) decoratedNetwork.getPassivNoEnergyList().add(new Passiv((HolonObject) simpleNode.tag)); } // Convert all edges for (GridEdge edge : grid.getEdges()) { SimpleGridEdge simpleGridEdge = (SimpleGridEdge) edge; decoratedNetwork.getDecoratedCableList().add( new DecoratedCable( ((IntermediateCableWithState) simpleGridEdge.tag).getModel(), DecoratedCable.CableState.Working, (float) simpleGridEdge.power.real, (float) simpleGridEdge.loss.real)); } decoratedNetwork.calculateStates(); } } private static synchronized Set getAllContextFromHolonObjects(List objects) { HashSet contextSet = new HashSet<>(); for (AbstractCanvasObject object : objects) if (object.tag instanceof HolegPowerFlowContext) contextSet.add((HolegPowerFlowContext) object.tag); return contextSet; } public static synchronized Set getALlContext() { return HolegGateway.getAllContextFromHolonObjects(SingletonControl.getInstance().getControl().getModel().getAllHolonObjectsOnCanvas()); } private static synchronized HolegPowerFlowContext getContextFromHolonObjects(List objects) { if (objects.size() == 0) return null; HolegPowerFlowContext context = null; for (AbstractCanvasObject object : objects) { if (object.tag instanceof HolegPowerFlowContext) { if (context == null) context = (HolegPowerFlowContext) object.tag; else { context.stopSolver(); object.tag = null; } } } if (context == null) { context = new HolegPowerFlowContext(); objects.get(0).tag = context; } return context; } public static synchronized void solve(PowerFlowSettings settings, MinimumNetwork minimumNetwork, int iteration, FlexManager flexManager, DecoratedNetwork network) { // Find context HolegPowerFlowContext context = getContextFromHolonObjects(minimumNetwork.getHolonObjectList()); if (context == null) return; // Solve with context solve(settings, context, minimumNetwork, iteration, flexManager, network); } private static synchronized void solve(PowerFlowSettings settings, HolegPowerFlowContext context, MinimumNetwork minimumNetwork, int iteration, FlexManager flexManager, DecoratedNetwork network) { if (settings == null) throw new IllegalArgumentException("settings is null"); if (context == null) throw new IllegalArgumentException("context is null"); if (minimumNetwork == null) throw new IllegalArgumentException("minimumNetwork is null"); if (network == null) throw new IllegalArgumentException("network is null"); // If we should show this solved grid if (context.showGridForVisual != null) { decorateNetwork(minimumNetwork, iteration, flexManager, network, context.showGridForVisual); context.showGridForVisual = null; return; } boolean solve = !PowerFlowAnalysisMenu.getInstance().areUpdatesDisabled(); Grid grid = convert(minimumNetwork, iteration, flexManager); // Check if the grid is equal to one already solved if (settings.onlyUpdateGridWhenChanged) { for (Grid lastSolved : context.lastSolvedGrids) { if (GridComparator.isEqual(lastSolved, grid)) { decorateNetwork(minimumNetwork, iteration, flexManager, network, lastSolved); return; } } // Only remember grid when solving if (solve) { // Keep size constrained to 32 saved grids if (context.lastSolvedGrids.size() >= 32) context.lastSolvedGrids.remove(0); // Grid is updated by solver directly, so we can save the reference to the grid context.lastSolvedGrids.add(grid); } } // Stop old solver context.stopSolver(); // Create solver job Thread solverJob = new Thread(() -> { long start = System.nanoTime(); GridSolverResult result = null; // Starting solving when requested if (solve) { HolegPowerFlow powerFlow = new HolegPowerFlow(); result = powerFlow.solve(grid, settings); } // Decorate network decorateNetwork(minimumNetwork, iteration, flexManager, network, grid); context.solverTimeMilliseconds = (System.nanoTime() - start) / 1e6f; // Update canvas and other visuals context.showGridForVisual = grid; SingletonControl.getInstance().getControl().calculateStateAndVisualForCurrentTimeStep(); // Show result message box if (result != null && PowerFlowAnalysisMenu.getInstance().shouldShowResult()) SolveResultMessageBox.show(result); }); // Wait or save solver job try { if (settings.waitForSolverJob) { // Start and wait till solver job is finished solverJob.start(); solverJob.join(); } else { // Render the non-solved grid and start the real solver job decorateNetwork(minimumNetwork, iteration, flexManager, network, grid); context.solverJob = solverJob; solverJob.start(); } } catch(InterruptedException e) { e.printStackTrace(); } } }