package blackstart; import java.awt.*; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import javax.swing.*; import api.AddOn; import classes.*; import ui.controller.Control; import classes.StorageProductionController; public class ControlAlgorithm implements AddOn { // Gui Part: private Control control; private JTextArea textArea; private JPanel content = new JPanel(); // ProgressBar private long startTime; private Thread runThread; private HolonObject powerplant; private TextField blackstartEnergyrequierementTextfield; private TextField blackstartSuccessTimeTextfield; private TextField powerplantMaxOutputTextfield; private TextField blackstartStartTimeTextfield; private TextField simulationDurationTextfield; private TextField storageStartCharge; private TextField carStartCharge; private TextField waitBetweenIterations; private TextField fileNameTextfield; private TextField schedulTextfield; private TextField renewableTextfield; private TextField addBatteryTextfield; private TextField addBatteryTypeTextfield; private TextField removeBatteryTextfield; private TextField removeBatteryTypeTextfield; private int blackstartSuccessTime; private int blackstartStartTime; private int blackstartRunningCounter; private float powerplantMaxOutput; private List renewableProducers; private List consumers; private StorageProductionController SPC; private int scheduleKind; private int totalNumberOfHouses; private Path file; private ArrayList lines; public static void main(String[] args) { JFrame newFrame = new JFrame("exampleWindow"); ControlAlgorithm instance = new ControlAlgorithm(); newFrame.setContentPane(instance.getPanel()); newFrame.pack(); newFrame.setVisible(true); newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public ControlAlgorithm() { content.setLayout(new BorderLayout()); textArea = new JTextArea(); textArea.setEditable(false); JScrollPane scrollPane = new JScrollPane(textArea); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createOptionPanel(), scrollPane); splitPane.setResizeWeight(0.0); content.add(splitPane, BorderLayout.CENTER); content.setPreferredSize(new Dimension(1000, 800)); } public JPanel createOptionPanel() { JPanel optionPanel = new JPanel(new BorderLayout()); JScrollPane scrollPane = new JScrollPane(createParameterPanel()); scrollPane.setBorder(BorderFactory.createTitledBorder("Parameter")); optionPanel.add(scrollPane, BorderLayout.CENTER); optionPanel.add(createButtonPanel(), BorderLayout.PAGE_END); return optionPanel; } private Component createParameterPanel() { JPanel parameterPanel = new JPanel(null); parameterPanel.setPreferredSize(new Dimension(510, 300)); blackstartEnergyrequierementTextfield = new TextField("5000000"); blackstartEnergyrequierementTextfield.setBounds(10, 10, 95, 20); parameterPanel.add(blackstartEnergyrequierementTextfield); JLabel blackstartEnergyrequierementLabel = new JLabel("Blackstart Energyrequirement in Watt"); blackstartEnergyrequierementLabel.setBounds(110, 10, 300, 20); parameterPanel.add(blackstartEnergyrequierementLabel); blackstartSuccessTimeTextfield = new TextField("30"); blackstartSuccessTimeTextfield.setBounds(10, 35, 95, 20); parameterPanel.add(blackstartSuccessTimeTextfield); JLabel blackstartSuccessTimeLabel = new JLabel("Time for successfull blackstart in minutes"); blackstartSuccessTimeLabel.setBounds(110, 35, 300, 20); parameterPanel.add(blackstartSuccessTimeLabel); blackstartStartTimeTextfield = new TextField("15"); blackstartStartTimeTextfield.setBounds(10, 60, 95, 20); parameterPanel.add(blackstartStartTimeTextfield); JLabel blackstartStartTimeLabel = new JLabel("Starttime for the blackstart"); blackstartStartTimeLabel.setBounds(110, 60, 300, 20); parameterPanel.add(blackstartStartTimeLabel); simulationDurationTextfield = new TextField("500"); simulationDurationTextfield.setBounds(10, 85, 95, 20); parameterPanel.add(simulationDurationTextfield); JLabel simulationDurationLabel = new JLabel("How long should the simulation run?"); simulationDurationLabel.setBounds(110, 85, 300, 20); parameterPanel.add(simulationDurationLabel); powerplantMaxOutputTextfield = new TextField("40000000"); powerplantMaxOutputTextfield.setBounds(10, 110, 95, 20); parameterPanel.add(powerplantMaxOutputTextfield); JLabel powerplantMaxOutputLabel = new JLabel("Powerplant Output afer Blackstart"); powerplantMaxOutputLabel.setBounds(110, 110, 300, 20); parameterPanel.add(powerplantMaxOutputLabel); storageStartCharge = new TextField("25"); storageStartCharge.setBounds(10, 135, 95, 20); parameterPanel.add(storageStartCharge); JLabel storageStartChargeLabel = new JLabel("Storage soc at start in %"); storageStartChargeLabel.setBounds(110, 135, 300, 20); parameterPanel.add(storageStartChargeLabel); carStartCharge = new TextField("50"); carStartCharge.setBounds(10, 160, 95, 20); parameterPanel.add(carStartCharge); JLabel carStartChargeLabel = new JLabel("Car soc at start in %"); carStartChargeLabel.setBounds(110, 160, 300, 20); parameterPanel.add(carStartChargeLabel); waitBetweenIterations = new TextField("0"); waitBetweenIterations.setBounds(10, 205, 95, 20); parameterPanel.add(waitBetweenIterations); JLabel waitBetweenIterationsLabel = new JLabel("Wait time between iterations"); waitBetweenIterationsLabel.setBounds(110, 205, 300, 20); parameterPanel.add(waitBetweenIterationsLabel); ////////collums fileNameTextfield = new TextField("Eval.txt"); fileNameTextfield.setBounds(425, 10, 95, 20); parameterPanel.add(fileNameTextfield); JLabel fileNameLabel = new JLabel("Filename"); fileNameLabel.setBounds(530, 10, 300, 20); parameterPanel.add(fileNameLabel); schedulTextfield = new TextField("0"); schedulTextfield.setBounds(425, 35, 95, 20); parameterPanel.add(schedulTextfield); JLabel scheduleLabel = new JLabel("Schedule: opt=0,simpl=1,rnd=2"); scheduleLabel.setBounds(530, 35, 300, 20); parameterPanel.add(scheduleLabel); renewableTextfield = new TextField("300"); renewableTextfield.setBounds(425, 60, 95, 20); parameterPanel.add(renewableTextfield); JLabel renewableLabel = new JLabel("renewable power per element in watt"); renewableLabel.setBounds(530, 60, 300, 20); parameterPanel.add(renewableLabel); // addBatteryTextfield = new TextField("0"); // addBatteryTextfield.setBounds(425, 110, 95, 20); // parameterPanel.add(addBatteryTextfield); // // JLabel addBatteryLabel = new JLabel("add number of certain batterytype"); // addBatteryLabel.setBounds(530, 110, 300, 20); // parameterPanel.add(addBatteryLabel); // // addBatteryTypeTextfield = new TextField("Car"); // addBatteryTypeTextfield.setBounds(425, 135, 95, 20); // parameterPanel.add(addBatteryTypeTextfield); // // JLabel addBatteryTypeLabel = new JLabel("What kind of battery to add"); // addBatteryTypeLabel.setBounds(530, 135, 300, 20); // parameterPanel.add(addBatteryTypeLabel); // // removeBatteryTextfield = new TextField("0"); // removeBatteryTextfield.setBounds(425, 160, 95, 20); // parameterPanel.add(removeBatteryTextfield); // // JLabel removeBatteryLabel = new JLabel("remove number of certain batterytype"); // removeBatteryLabel.setBounds(530, 160, 300, 20); // parameterPanel.add(removeBatteryLabel); // // removeBatteryTypeTextfield = new TextField("Car"); // removeBatteryTypeTextfield.setBounds(425, 205, 95, 20); // parameterPanel.add(removeBatteryTypeTextfield); // // JLabel removeBatteryTypeLabel = new JLabel("What kind of battery to remove"); // removeBatteryTypeLabel.setBounds(530, 205, 300, 20); // parameterPanel.add(removeBatteryTypeLabel); return parameterPanel; } public JPanel createButtonPanel() { JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); JButton runButton = new JButton("Run"); runButton.addActionListener(actionEvent -> { Runnable task = this::run; runThread = new Thread(task); runThread.start(); }); buttonPanel.add(runButton); return buttonPanel; } private void run() { clear(); disableGuiInput(true); startTimer(); initAlgo(); printElapsedTime(); disableGuiInput(false); } private void disableGuiInput(boolean bool) { control.guiDisable(bool); } @Override public JPanel getPanel() { return content; } @Override public void setController(Control control) { this.control = control; } private void clear() { textArea.setText(""); } private void println(String message) { lines.add(message); textArea.append(message + "\n"); } private void startTimer() { startTime = System.currentTimeMillis(); } private void printElapsedTime() { long elapsedMilliSeconds = System.currentTimeMillis() - startTime; println("Execution Time of Algo in Milliseconds:" + elapsedMilliSeconds); } /////////////////////////////////////////////////////////////////////////////////// /** * */ private void initAlgo() { try { // init renewableProducers = getRenewableProducers(); consumers = getConsumers(); // addCertainKindOfBatteries(Integer.parseInt(addBatteryTextfield.getText()),addBatteryTypeTextfield.getText()); // removeCertainKindOfBatteries(Integer.parseInt(removeBatteryTextfield.getText()), removeBatteryTypeTextfield.getText()); totalNumberOfHouses = consumers.size(); lines = new ArrayList(); lines.add(fileNameTextfield.getText()); if(control.getSimManager().getPowerplant() != null){ powerplant = control.getSimManager().getPowerplant();// DANGER DONT GIVE NULL }else{ println("No Power plant in model"); return; } setPowerPlantBlackstartResistance(-Float.parseFloat(blackstartEnergyrequierementTextfield.getText())); if(getEnergyRequiredForPowerplantBlackstart() != 0){ SPC = new StorageProductionController(getStorageElements(), getEnergyRequiredForPowerplantBlackstart());// DANGER DONT GIVE NULL }else{ println("No blackstart Power Plant in Model"); return; } control.getModel().setResistanceCalculator(new ResistanceCalculator( 230, 10000, 35, 25,0.017, 0.017)); control.getModel().getResistanceCalculator().setDistancesToCalcResistance(powerplant); blackstartRunningCounter = 0; deactivateBlackstart(); control.getModel().setCurIteration(0); // prepare model ///////// setRenewableElements(Float.parseFloat(renewableTextfield.getText())); disablePowerplantProduction(); enableAllConsumers(); SPC.setAllStorageToStandy(); // TODO: prios? ///////// // Get parameters from textfields scheduleKind = Integer.parseInt(schedulTextfield.getText()); setPowerPlantBlackstartResistance(-Float.parseFloat(blackstartEnergyrequierementTextfield.getText())); blackstartSuccessTime = Integer.parseInt(blackstartSuccessTimeTextfield.getText()); powerplantMaxOutput = Float.parseFloat(powerplantMaxOutputTextfield.getText()); blackstartStartTime = Integer.parseInt(blackstartStartTimeTextfield.getText()); control.getModel().setIterations(Integer.parseInt(simulationDurationTextfield.getText())); for (StorageElement se : getStorageElements()) { if (se.getEleName().startsWith("Car")) { se.setStateOfCharge(Float.parseFloat(carStartCharge.getText())); } else { se.setStateOfCharge(Float.parseFloat(storageStartCharge.getText())); } } file = Paths.get(fileNameTextfield.getText()); updateVisual(); if (blackstartStartTime + blackstartSuccessTime > control.getModel().getIterations() - 1) { println("No Time for the blackstart, use working numbers"); } else { blackstartMain(control.getModel().getCurIteration()); } } catch (NumberFormatException e) { println("Worng Input, only numbers please"); } } private void blackstartMain(int curIteration) { try { Thread.sleep(Integer.parseInt(waitBetweenIterations.getText())); } catch (InterruptedException e) { e.printStackTrace(); } control.getModel().setCurIteration(curIteration); if (control.getSimManager().blackstartRunning()) { if (!blackstartAlgo()) { // blackstart for this iteration was not successfull deactivateBlackstart(); updateVisual(); println("Simulation of blackstart failed in Iteration: " + curIteration); writeOutputTxt(); } else { // blackstart for this iteration was successfull blackstartRunningCounter++; if (blackstartRunningCounter == blackstartSuccessTime) { // blackstart was successfull for the needed iterations SPC.setAllStorageToStandy(); deactivateBlackstart(); enableAllConsumers(); updateVisual(); println("Simulation of blackstart Successfull in Iteration: " + curIteration); writeOutputTxt(); } else { // blackstart not finished yet updateVisual(); blackstartMain(curIteration + 1); } } } else { // blackstart has not started yet if (curIteration == blackstartStartTime) { activateBlackstart(); disableConsumers(); blackstartMain(curIteration); } else { updateVisual(); blackstartMain(curIteration + 1); } } } /** * TODO: global resistance calculator? * * * maybes: * * TODO: prios fuer elemente anschalten * * TODO: batterie status wechesel fuehrt zu unterversorgung in GUI FIX?: in storage if bei charge auskommentieren * * TODO: batterie laden prios? entfernung? doppelt sortieren * * @return true or false depending on whether the blackstart was successful for * this iteration */ private boolean blackstartAlgo() { printCurrentEnergyState(); if (currentRenewableProduction() < getEnergyRequiredForPowerplantBlackstart()) { // renewable energy production is not sufficient for the blackstart if (SPC.currentPossibleStorageProduction() >= getEnergyRequiredForPowerplantBlackstart() - currentRenewableProduction()) {// is there currently enough power available from storage? SPC.setAllStorageToStandy();//TODO: placement SPC.scheduleDischarging(getEnergyRequiredForPowerplantBlackstart() - currentRenewableProduction(), scheduleKind); rampUpPowerplant(); enableConsumers(getPowerplantProduction()); return true; } else { // blackstart has failed SPC.setAllStorageToStandy(); println("Not enough storage energy available"); return false; } } else {try { Files.write(file, lines, StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } //TODO: disable storage? // renewable energy production is sufficient for the blackstart rampUpPowerplant(); enableConsumers( currentRenewableProduction() - getEnergyRequiredForPowerplantBlackstart() + getPowerplantProduction()); return true; } } private ArrayList getStorageElements() { ArrayList storageElements = new ArrayList<>(); for (HolonObject holonObject : control.getModel().getAllHolonObjectsOnCanvas()) { for (HolonElement ele : holonObject.getElements()) { if(ele instanceof StorageElement){ storageElements.add((StorageElement) ele); } } } return storageElements; } private void disableConsumers() { // TODO: disableBatteryLoading? will ich das wirklich? // SPC.disableStorageProduction(); for (HolonObject consumer : consumers) { for (HolonElement ele : consumer.getElements()) { if (ele.isActive() && ele.isConsumer()) { ele.setActive(false); } } } } private void enableConsumers(float energyAvailable) { // println("current pp production: " + getPowerplantProduction()); // println("energy available for consumers" + energyAvailable); // Damit wir immer die gleiche ausgangslage haben //TODO: wirklich? disableConsumers(); // TODO: das ganze lieber mit prirotaeten for (HolonObject consumer : consumers) { for (HolonElement ele : consumer.getElements()) { if (energyAvailable > 0 && energyAvailable - Math.abs(ele.getEnergyPerElement() * ele.getAmount()) >= 0) {//TODO: getenergy ist hier falsch if (!ele.isActive()) { ele.setActive(true); energyAvailable = energyAvailable - Math.abs(ele.getEnergyPerElement() * ele.getAmount());// + // since // its // negative } } else { return; } } } } private void enableAllConsumers() { for (HolonObject consumer : consumers) { for (HolonElement ele : consumer.getElements()) { if (!ele.isActive() && ele.isConsumer()) { ele.setActive(true); } }//TODO: storage? } } private void setRenewableElements(float energy){ for (HolonObject house : renewableProducers) { for (HolonElement ele : house.getElements()) { if (ele.getEleName().equals("Solar Panels")) {// TODO: hier muss noch mehr dazu ele.setEnergyPerElement( control.getModel().getResistanceCalculator().calcEnergyAfterResistance( energy, ele.getLowDistance(), ele.getHighDistance(), getEnergyRequiredForPowerplantBlackstart())); } } } } private float currentRenewableProduction() { float production = 0; for (HolonObject house : renewableProducers) { for (HolonElement ele : house.getElements()) { if (ele.getEleName().equals("Solar Panels")) {// TODO: hier muss noch mehr dazu production = production + ele.getEnergyAtTimeStep(control.getModel().getCurIteration()); } } } return production; } private void rampUpPowerplant() { for (HolonElement ele : powerplant.getElements()) { if (ele.getEleName().equals("Power")) { ele.setEnergyPerElement(ele.getEnergyPerElement() + powerplantMaxOutput / blackstartSuccessTime); } } } private float getPowerplantProduction() { float totalProduction = 0; for (HolonElement ele : powerplant.getElements()) { if (ele.getEleName().equals("Power")) { totalProduction = ele.getEnergyPerElement(); } } return totalProduction; } private void disablePowerplantProduction() { for (HolonElement ele : powerplant.getElements()) { if (ele.getEleName().equals("Power")) { ele.setEnergyPerElement(0); } } } private float getEnergyRequiredForPowerplantBlackstart() { for (HolonElement ele : powerplant.getElements()) { if (ele.getEleName().equals("Blackstart")) { return -ele.getEnergyPerElement(); } } return 0; } private void setPowerPlantBlackstartResistance(float resistance) { for (HolonElement ele : powerplant.getElements()) { if (ele.getEleName().equals("Blackstart")) { ele.setEnergyPerElement(resistance); } } } private void activateBlackstart() { for (HolonElement ele : powerplant.getElements()) { if (ele.getEleName().equals("Blackstart")) { ele.setActive(true); } } } private void deactivateBlackstart() { for (HolonElement ele : powerplant.getElements()) { if (ele.getEleName().equals("Blackstart")) { ele.setActive(false); } } } private LinkedList getRenewableProducers() { LinkedList list = new LinkedList<>(); for (HolonObject holonObject : control.getModel().getAllHolonObjectsOnCanvas()) { if (holonObject.getObjName().contentEquals("House")) {// TODO: das reicht so nicht da muss noch gecheckt // werden ob es renewables gibt list.add(holonObject); } } return list; } private LinkedList getConsumers() { LinkedList list = new LinkedList<>(); for (HolonObject holonObject : control.getModel().getAllHolonObjectsOnCanvas()) { if (holonObject.getObjName().contentEquals("House")) {// TODO: das reicht so nicht da muss noch gecheckt // werden ob es consumer gibt list.add(holonObject); } } return list; } private void removeCertainKindOfBatteries(int amount, String kind){ int start = highestAmountOfBatteriesOfCertainKindInALLHouse(kind); while(amount > 0){ for (HolonObject hO : consumers){ if(numberOfCertainKindOfBatteryPerHouse(hO, kind) == start) { if (delSingleElem(hO, kind)) { amount--; } } if(amount == 0){ return; } } start--; } } private boolean delSingleElem(HolonObject hO, String kind){ for(HolonElement ele : hO.getElements()){ if(ele.getEleName().startsWith(kind)){ // control.deleteElementCanvas(hO.getId(),ele.getId()); hO.getElements().remove(ele); return true; } } return false; } private int highestAmountOfBatteriesOfCertainKindInALLHouse(String kind){ int count = 0; for (HolonObject hO : consumers){ int eleCount = numberOfCertainKindOfBatteryPerHouse(hO, kind); if(eleCount > count){ count = eleCount; }; } return count; } private void addCertainKindOfBatteries(int amount, String kind){ int start = 0; while(amount > 0){ for (HolonObject hO : consumers){ if(numberOfCertainKindOfBatteryPerHouse(hO, kind) <= start){ if(kind.startsWith("Car")){ hO.addElement(new StorageElement(kind + start, 1, 0, control.getModel(), 75000, 22000, 22000)); }else{ hO.addElement(new StorageElement(kind + start, 1, 0, control.getModel(), 13500, 46000, 4600)); } amount--; } if(amount == 0){ return; } } start++; } } private int numberOfCertainKindOfBatteryPerHouse(HolonObject house, String kind){ int count = 0; for(HolonElement ele : house.getElements()){ if(ele.getEleName().startsWith(kind)){ count++; } } return count; } private void writeOutputTxt(){ println("totalSOC: " + SPC.getTotalSoc() + "W/m"); try { Files.write(file, lines, StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } } private void printCurrentEnergyState(){ println("CURRENT ALGORITHM ITERATION: "+ control.getModel().getCurIteration()); println("blackstart resi: " + getEnergyRequiredForPowerplantBlackstart()); println("renewable: " + currentRenewableProduction()); println("totalnumber of houses: " + totalNumberOfHouses); println("totalcars: " + SPC.getTotalCarNumber() + " totalhomebatteries: " + SPC.getTotalHomeBatteryNumber()); println("possiblestorage: " + SPC.currentPossibleStorageProduction()); println("totalSOC: " + SPC.getTotalSoc() + "W/m"); for (StorageElement ele : getStorageElements()) { println(ele.getEleName() + " " + ele.getId() + ", SOC: " + (ele.getStateOfCharge()/60)/1000 + "kWh," + " SOC%: " + ele.getStateOfChargeInPercent() *100 +"%" /*+ " SOC: " + ele.getStateOfCharge() + " watt/min"*/ // + " nominal power: " + ele.getNominalOutRatio()/1000 + " kW, " + " OutPower: "+ ele.getCurrentMaxOutRatio()/1000 + " kW," + " dist: " + (ele.getLowDistance()+ele.getHighDistance())); } } /** * To let the User See the current state without touching the Canvas. */ private void updateVisual() { // System.out.println("Start updateVisual in Iteration: " + control.getModel().getCurIteration()); control.calculateStateAndVisualForCurrentTimeStep(); control.updateCanvas(); // System.out.println("Finish updateVisual in Iteration: " + control.getModel().getCurIteration()); } }