HolegGateway.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. package holeg;
  2. import classes.AbstractCanvasObject;
  3. import classes.HolonElement;
  4. import classes.HolonObject;
  5. import classes.Node;
  6. import holeg.model.*;
  7. import holeg.power_flow.ComplexNumber;
  8. import holeg.simple_grid.SimpleGridBuilder;
  9. import holeg.simple_grid.SimpleGridEdge;
  10. import holeg.simple_grid.SimpleGridNode;
  11. import holeg.ui.PowerFlowAnalysisMenu;
  12. import holeg.ui.SolveResultMessageBox;
  13. import ui.controller.FlexManager;
  14. import ui.controller.SingletonControl;
  15. import ui.model.*;
  16. import ui.view.GUI;
  17. import javax.swing.*;
  18. import java.awt.*;
  19. import java.util.*;
  20. import java.util.List;
  21. import java.util.stream.Collectors;
  22. public class HolegGateway {
  23. private static ThreadLocal<Boolean> onlyUpdateVisual = new ThreadLocal<Boolean>();
  24. private static Grid convert(MinimumNetwork network, int iteration, FlexManager flexManager) {
  25. SimpleGridBuilder gridBuilder = new SimpleGridBuilder();
  26. HashMap<AbstractCanvasObject, SimpleGridNode> canvasToGrid = new HashMap<>();
  27. for (HolonObject object : network.getHolonObjectList()) {
  28. double power = object.getEnergyAtTimeStep(iteration);
  29. double reactivePower = object.getReactiveEnergyAtTimeStep(iteration);
  30. SimpleGridNode node;
  31. // Create house or generator
  32. if (power <= 0)
  33. node = gridBuilder.addHouse(new ComplexNumber(-power, reactivePower));
  34. else
  35. node = gridBuilder.addGenerator(new ComplexNumber(power, reactivePower));
  36. node.tag = object;
  37. // Find voltage
  38. Optional<HolonElement> voltageOverride = object.getElements().stream().filter(e -> e.getEleName().equalsIgnoreCase("__VOLTAGE")).findFirst();
  39. voltageOverride.ifPresent(e -> node.voltage = e.getEnergyAtTimeStep(0));
  40. // Find type by design
  41. if (object.getElements().stream().anyMatch(e -> e.getEleName().equalsIgnoreCase("SLACK")))
  42. node.typeByDesign = NodeType.Slack;
  43. else if (object.getElements().stream().anyMatch(e -> e.getEleName().equalsIgnoreCase("PV")))
  44. node.typeByDesign = NodeType.PV;
  45. else if (object.getElements().stream().anyMatch(e -> e.getEleName().equalsIgnoreCase("PQ")))
  46. node.typeByDesign = NodeType.PQ;
  47. else
  48. node.typeByDesign = NodeType.Bus;
  49. canvasToGrid.put(object, node);
  50. }
  51. // Add all switches and nodes
  52. for (AbstractCanvasObject object : network.getNodeAndSwitches()) {
  53. SimpleGridNode node = gridBuilder.addHouse(new ComplexNumber(0, 0));
  54. node.tag = object;
  55. node.typeByDesign = NodeType.Bus;
  56. canvasToGrid.put(object, node);
  57. }
  58. // Add all cables
  59. for (IntermediateCableWithState cable : network.getEdgeList()) {
  60. SimpleGridNode a = canvasToGrid.get(cable.getModel().getA());
  61. SimpleGridNode b = canvasToGrid.get(cable.getModel().getB());
  62. if (a == null || b == null)
  63. continue;
  64. SimpleGridEdge edge = gridBuilder.connect(a, b, Math.max(1, cable.getModel().getRealLength()));
  65. edge.overrideInPerUnit = cable.getModel().getOverrideInPerUnit();
  66. edge.overrideImpedance = new ComplexNumber(cable.getModel().getOverrideResistance(), cable.getModel().getOverrideReactance());
  67. edge.overrideShuntSusceptance = cable.getModel().getOverrideShuntSusceptance();
  68. edge.overrideTapRatio = cable.getModel().getOverrideTapRatio();
  69. edge.tag = cable;
  70. }
  71. return gridBuilder.getGrid();
  72. }
  73. private static void decorateNetwork(MinimumNetwork network, int iteration, FlexManager flexManager, DecoratedNetwork decoratedNetwork, Grid grid) {
  74. synchronized (decoratedNetwork.getLockObject()) {
  75. decoratedNetwork.clear();
  76. // Convert all nodes
  77. for (GridNode node : grid.getNodes()) {
  78. SimpleGridNode simpleNode = (SimpleGridNode) node;
  79. // Create supplier, consumer or passiv object
  80. if (node.getPowerGeneration().lenSquared() > 0)
  81. decoratedNetwork.getSupplierList().add(new Supplier((HolonObject) simpleNode.tag, (float) node.getPowerGeneration().real, 0, simpleNode.getVoltage(), simpleNode.phaseDegrees, simpleNode.getTypeSolved() == NodeType.Slack, simpleNode.index));
  82. else if (node.getPowerConsumption().lenSquared() > 0)
  83. decoratedNetwork.getConsumerList().add(new Consumer((HolonObject) simpleNode.tag, (float) node.getPowerConsumption().real, simpleNode.getVoltage(), simpleNode.phaseDegrees, Math.cos(simpleNode.getPowerConsumption().angle()), simpleNode.getTypeSolved() == NodeType.Slack, simpleNode.index));
  84. else if (simpleNode.tag instanceof HolonObject)
  85. decoratedNetwork.getPassivNoEnergyList().add(new Passiv((HolonObject) simpleNode.tag, simpleNode.index));
  86. }
  87. // Convert all edges
  88. for (GridEdge edge : grid.getEdges()) {
  89. SimpleGridEdge simpleGridEdge = (SimpleGridEdge) edge;
  90. decoratedNetwork.getDecoratedCableList().add(
  91. new DecoratedCable(
  92. ((IntermediateCableWithState) simpleGridEdge.tag).getModel(),
  93. DecoratedCable.CableState.Working,
  94. (float) simpleGridEdge.power.real,
  95. (float) simpleGridEdge.loss.real));
  96. }
  97. decoratedNetwork.calculateStates();
  98. }
  99. }
  100. private static synchronized Set<HolegPowerFlowContext> getAllContextFromHolonObjects(List<HolonObject> objects) {
  101. HashSet<HolegPowerFlowContext> contextSet = new HashSet<>();
  102. for (AbstractCanvasObject object : objects)
  103. if (object.tag instanceof HolegPowerFlowContext)
  104. contextSet.add((HolegPowerFlowContext) object.tag);
  105. return contextSet;
  106. }
  107. public static synchronized Set<HolegPowerFlowContext> getALlContext() {
  108. return HolegGateway.getAllContextFromHolonObjects(SingletonControl.getInstance().getControl().getModel().getAllHolonObjectsOnCanvas());
  109. }
  110. private static synchronized HolegPowerFlowContext getContextFromHolonObjects(List<HolonObject> objects) {
  111. if (objects.size() == 0)
  112. return null;
  113. HolegPowerFlowContext context = null;
  114. for (AbstractCanvasObject object : objects) {
  115. if (object.tag instanceof HolegPowerFlowContext) {
  116. if (context == null)
  117. context = (HolegPowerFlowContext) object.tag;
  118. else {
  119. context.stopSolver();
  120. object.tag = null;
  121. }
  122. }
  123. }
  124. if (context == null) {
  125. context = new HolegPowerFlowContext();
  126. objects.get(0).tag = context;
  127. }
  128. return context;
  129. }
  130. public static void solve(PowerFlowSettings settings, MinimumNetwork minimumNetwork, int iteration, FlexManager flexManager, DecoratedNetwork network) {
  131. Thread solverWrapper = new Thread(() -> {
  132. try {
  133. solveInternal(settings, minimumNetwork, iteration, flexManager, network);
  134. } catch (Exception e) {
  135. SolveResultMessageBox.showInternalError(e);
  136. }
  137. });
  138. try {
  139. solverWrapper.setName("Solver Wrapper " + Long.toHexString(solverWrapper.getId()));
  140. solverWrapper.start();
  141. solverWrapper.join(4000);
  142. if (solverWrapper.isAlive()) {
  143. solverWrapper.stop();
  144. SolveResultMessageBox.showSolverTookTooLongToStart();
  145. }
  146. } catch (Exception e) {
  147. SolveResultMessageBox.showInternalError(e);
  148. }
  149. }
  150. private static void solveInternal(PowerFlowSettings settings, MinimumNetwork minimumNetwork, int iteration, FlexManager flexManager, DecoratedNetwork network) {
  151. // Find context
  152. HolegPowerFlowContext context = getContextFromHolonObjects(minimumNetwork.getHolonObjectList());
  153. if (context == null)
  154. return;
  155. // Solve with context
  156. solve(settings, context, minimumNetwork, iteration, flexManager, network);
  157. }
  158. private static void solve(PowerFlowSettings settings, HolegPowerFlowContext context, MinimumNetwork minimumNetwork, int iteration, FlexManager flexManager, DecoratedNetwork network) {
  159. if (settings == null)
  160. throw new IllegalArgumentException("settings is null");
  161. if (context == null)
  162. throw new IllegalArgumentException("context is null");
  163. if (minimumNetwork == null)
  164. throw new IllegalArgumentException("minimumNetwork is null");
  165. if (network == null)
  166. throw new IllegalArgumentException("network is null");
  167. // If we should show this solved grid
  168. if (context.showGridForVisual != null) {
  169. decorateNetwork(minimumNetwork, iteration, flexManager, network, context.showGridForVisual);
  170. context.showGridForVisual = null;
  171. return;
  172. }
  173. synchronized (context.lock) {
  174. boolean solve = !PowerFlowAnalysisMenu.getInstance().areUpdatesDisabled();
  175. Grid grid = convert(minimumNetwork, iteration, flexManager);
  176. // Check if the grid is equal to one already solved
  177. if (settings.onlyUpdateGridWhenChanged) {
  178. for (Grid lastSolved : context.lastSolvedGrids) {
  179. if (GridComparator.isEqual(lastSolved, grid)) {
  180. decorateNetwork(minimumNetwork, iteration, flexManager, network, lastSolved);
  181. return;
  182. }
  183. }
  184. // Only remember grid when solving
  185. if (solve) {
  186. // Keep size constrained to 32 saved grids
  187. if (context.lastSolvedGrids.size() >= 32)
  188. context.lastSolvedGrids.remove(0);
  189. // Grid is updated by solver directly, so we can save the reference to the grid
  190. context.lastSolvedGrids.add(grid);
  191. }
  192. }
  193. // We got no solution for this grid
  194. if (onlyUpdateVisual.get() != null && onlyUpdateVisual.get()) {
  195. decorateNetwork(minimumNetwork, iteration, flexManager, network, grid);
  196. return;
  197. }
  198. // Stop old solver
  199. context.stopSolver();
  200. // Create solver job
  201. Thread solverJob = new Thread(() -> {
  202. try {
  203. long start = System.nanoTime();
  204. GridSolverResult result = null;
  205. // Starting solving when requested
  206. if (solve) {
  207. HolegPowerFlow powerFlow = new HolegPowerFlow();
  208. result = powerFlow.solve(grid, settings, context);
  209. }
  210. // Decorate network
  211. decorateNetwork(minimumNetwork, iteration, flexManager, network, grid);
  212. context.solverTimeMilliseconds = (System.nanoTime() - start) / 1e6f;
  213. // Update canvas and other visuals
  214. context.showGridForVisual = grid;
  215. onlyUpdateVisual.set(true);
  216. SingletonControl.getInstance().getControl().calculateStateAndVisualForCurrentTimeStep();
  217. onlyUpdateVisual.set(false);
  218. // Show result message box
  219. if (result != null && PowerFlowAnalysisMenu.getInstance().shouldShowResult())
  220. SolveResultMessageBox.show(result);
  221. }
  222. catch(Exception e) {
  223. SolveResultMessageBox.showInternalError(e);
  224. }
  225. });
  226. solverJob.setName("Solver 0x" + Integer.toHexString(context.hashCode()));
  227. // Wait or save solver job
  228. try {
  229. if (settings.waitForSolverJob) {
  230. // Start and wait till solver job is finished
  231. solverJob.start();
  232. solverJob.join();
  233. } else {
  234. // Render the non-solved grid and start the real solver job
  235. decorateNetwork(minimumNetwork, iteration, flexManager, network, grid);
  236. context.solverJob = solverJob;
  237. solverJob.start();
  238. }
  239. } catch (InterruptedException e) {
  240. e.printStackTrace();
  241. }
  242. }
  243. }
  244. }