HolegGateway.java 12 KB

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