From 6da78551794e6b69414f8e9f4e8b1fdb00bd0c16 Mon Sep 17 00:00:00 2001 From: GillisHommen <98752265+GillisHommen@users.noreply.github.com> Date: Mon, 8 Jul 2024 16:41:12 +0200 Subject: [PATCH] Added curtailment of electricity production as a generic GridConnection functionality When GC.v_enableCurtailment is true, production is curtailed to connection capacity. When there are multiple electricity production assets, the (merit) order they have in the collection c_productionAssets is used. --- Zero_engine.alp | 263 ++++++++++++++++++++++++----------------- database/db.properties | 4 +- database/db.script | 2 +- 3 files changed, 158 insertions(+), 111 deletions(-) diff --git a/Zero_engine.alp b/Zero_engine.alp index bd42b0c..ddb4459 100644 --- a/Zero_engine.alp +++ b/Zero_engine.alp @@ -4,7 +4,7 @@ AnyLogic Project File ************************************************* --> - + 1658477103134 @@ -8343,7 +8343,7 @@ f_initializeForecasts();]]> 1699275048295 - 801430 + 801450 false true @@ -8367,7 +8367,7 @@ f_initializeForecasts();]]> 1699275048309 - 801470 + 801490 false true @@ -8391,7 +8391,7 @@ f_initializeForecasts();]]> 1699275048324 - 801410 + 801430 false true @@ -8463,7 +8463,7 @@ f_initializeForecasts();]]> 1699275048369 - 801510 + 801530 false true @@ -8535,7 +8535,7 @@ f_initializeForecasts();]]> 1699275048412 - 801450 + 801470 false true @@ -8559,7 +8559,7 @@ f_initializeForecasts();]]> 1699275048425 - 801530 + 801550 false true @@ -8583,7 +8583,7 @@ f_initializeForecasts();]]> 1699275048440 - 801550 + 801570 false true @@ -10027,7 +10027,7 @@ f_initializeForecasts();]]> 1715671336391 - 801490 + 801510 false true @@ -10072,6 +10072,30 @@ f_initializeForecasts();]]> x.v_hydrogenElectricityConsumption_kW)]]> 672 + + 1720447715226 + + 801410 + + false + true + true + false + true + 1687075200000 + + + + + + + + + false + + max(0,x.v_curtailmentPowerElectric_kW))]]> + 672 + @@ -13022,6 +13046,9 @@ f_initializeForecasts();]]> + + + true @@ -17061,7 +17088,7 @@ import zeroPackage.ZeroAccumulator;]]> 1658499590783 - 1501250 + 1501280 false true @@ -17330,7 +17357,7 @@ import zeroPackage.ZeroAccumulator;]]> 1668610741368 - 1501170 + 1501200 false true @@ -17475,7 +17502,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671027786040 - 1501190 + 1501220 false true @@ -17488,7 +17515,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671028145282 true - 1501330 + 1501360 false true @@ -17501,7 +17528,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671028164395 true - 1501350 + 1501380 false true @@ -17514,7 +17541,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671028183310 true - 1501310 + 1501340 false true @@ -17527,7 +17554,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671028204660 true - 1501370 + 1501400 false true @@ -17540,7 +17567,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671028232758 true - 1501410 + 1501440 false true @@ -17553,7 +17580,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671028253782 true - 1501430 + 1501460 false true @@ -17579,7 +17606,7 @@ import zeroPackage.ZeroAccumulator;]]> true - 1501390 + 1501420 false true @@ -17592,7 +17619,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671028484635 true - 1501450 + 1501480 false true @@ -17605,7 +17632,7 @@ import zeroPackage.ZeroAccumulator;]]> 1671028484651 true - 1501470 + 1501500 false true @@ -19909,6 +19936,33 @@ import zeroPackage.ZeroAccumulator;]]> + + 1720442507543 + + 250300 + + false + true + true + + + + + + + + + 1720447120435 + + 1501150 + + false + true + true + + + + 1658499438204 @@ -20344,6 +20398,7 @@ import zeroPackage.ZeroAccumulator;]]> 1676965009213 + true 510240 false @@ -21213,7 +21268,7 @@ else { 1660212665961 - 800480 + 800500 false true @@ -21751,12 +21806,16 @@ v_batteryPowerElectric_kW = 0; v_windProductionElectric_kW = 0; v_pvProductionElectric_kW = 0; v_conversionPowerElectric_kW = 0; +v_curtailmentPowerElectric_kW = 0; c_tripTrackers.forEach(t -> t.manageActivities(energyModel.t_h*60)); f_operateFixedAssets(); f_operateFlexAssets(); +if (v_enableCurtailment) { + f_curtailment(); +} if (b_useHydrogenLocally && v_hydrogenInStorage_kWh > 0.1) { f_operateFuelCell(); @@ -22742,8 +22801,8 @@ if (j_ea instanceof J_EAVehicle) { p_primaryHeatingAsset = (J_EAConversion)j_ea; } else if (j_ea instanceof J_EAConversionHydrogenBurner) { p_primaryHeatingAsset = (J_EAConversion)j_ea; - } else if (j_ea instanceof J_EAConversionCurtailer) { - p_curtailer = (J_EAConversionCurtailer)j_ea; + //} else if (j_ea instanceof J_EAConversionCurtailer) { +// p_curtailer = (J_EAConversionCurtailer)j_ea; } } else if (j_ea instanceof J_EAStorage) { c_storageAssets.add((J_EAStorage)j_ea); @@ -23162,23 +23221,20 @@ v_currentPowerHydrogen_kW += arr[6] - arr[2]; v_currentPowerHeat_kW += arr[7] - arr[3]; v_currentPowerDiesel_kW += arr[8]; -//if (caller instanceof J_EAStorageElectric) { // || caller instanceof J_EAEV) { // for battery or EV, if energy is 'produced' (battery supplying electricity), substract this from the electricityConsumed instead of counting it as 'energy'production - //v_totalElectricityConsumed_MWh += caller.energyUse_kW * energyModel.p_timeStep_h / 1000; - //v_currentElectricityConsumption_kW += arr[4]; - //v_currentElectricityConsumption_kW -= arr[0]; +if (caller instanceof J_EAStorageElectric) { // Only allocate battery losses as consumption. Charging/discharging is neither production nor consumption. Do we need a 10th element in arr indicating power into storage?? v_currentEnergyConsumption_kW += max(0,arr[9]); v_currentElectricityConsumption_kW += max(0,arr[9]); -} else { // For other assets, - if (caller instanceof J_EAConversionCurtailer) { - v_currentEnergyProduction_kW -= max(0,arr[9]); - v_currentElectricityProduction_kW -= arr[4]; - } else { - v_currentEnergyProduction_kW += max(0,-arr[9]); - v_currentEnergyConsumption_kW += max(0,arr[9]); - v_currentElectricityConsumption_kW += arr[4]; - v_currentElectricityProduction_kW += arr[0]; - } -//} +} else if (caller instanceof J_EAProduction) { + v_currentEnergyProduction_kW += -arr[9]; // This enables J_EAProduction to use curtailer method and 'cancel' production! + v_curtailmentPowerElectric_kW += max(0,arr[9]); + v_currentElectricityProduction_kW += arr[0]; +} else { + v_currentEnergyProduction_kW += max(0,-arr[9]); + v_currentEnergyConsumption_kW += max(0,arr[9]); + v_currentElectricityConsumption_kW += arr[4]; + v_currentElectricityProduction_kW += arr[0]; +} + //if ( arr[4] > 0 && arr[3] > arr[4]) { if ( caller instanceof J_EAConversionHeatPump ) { //v_totalHeatProduced_MWh += max(0,(arr[3]-arr[4]) * energyModel.p_timeStep_h / 1000); // This should only be non-zero for heatpumps!! But this is method is highly unsafe... @@ -23401,14 +23457,12 @@ if (j_ea instanceof J_EAVehicle) { c_conversionAssets.remove((J_EAConversion)j_ea); if ( j_ea.energyAssetType == OL_EnergyAssetType.GAS_PIT | j_ea.energyAssetType == OL_EnergyAssetType.ELECTRIC_HOB){ p_cookingTracker = null; - } else if (j_ea instanceof J_EAConversionCurtailer) { - p_curtailer = null; } else if (j_ea instanceof J_EAConversionGasBurner) { p_primaryHeatingAsset = null; } else if (j_ea instanceof J_EAConversionHeatPump) { p_primaryHeatingAsset = null; - } else if (j_ea instanceof J_EAConversionCurtailer) { - p_curtailer = null; + //} else if (j_ea instanceof J_EAConversionCurtailer) { + // p_curtailer = null; } } else if (j_ea instanceof J_EAStorage) { c_storageAssets.remove((J_EAStorage)j_ea); @@ -23552,6 +23606,25 @@ if (v_currentPowerElectricity_kW > p_connectionCapacity_kW * 0.9 || v_currentPow v_hydrogenInStorage_kWh -= arr[6] * energyModel.p_timeStep_h; v_totalHydrogenUsed_MWh += arr[6] * energyModel.p_timeStep_h / 1000; } +}]]> + + + VOID + + 1720442672576 + + 800480 + + false + true + true + @@ -25890,7 +25963,7 @@ if (v_currentPowerElectricity_kW > p_connectionCapacity_kW * 0.9 || v_currentPow 1671027607665 - 2001140 + 2001170 false true @@ -25911,7 +25984,7 @@ if (v_currentPowerElectricity_kW > p_connectionCapacity_kW * 0.9 || v_currentPow 1671027820068 - 1201221 + 1201251 true true @@ -25935,7 +26008,7 @@ if (v_currentPowerElectricity_kW > p_connectionCapacity_kW * 0.9 || v_currentPow 1671027834321 - 2301207 + 2301237 false true @@ -25978,7 +26051,7 @@ if (v_currentPowerElectricity_kW > p_connectionCapacity_kW * 0.9 || v_currentPow 1671028103716 - 2001290 + 2001320 false true @@ -26020,7 +26093,7 @@ if (v_currentPowerElectricity_kW > p_connectionCapacity_kW * 0.9 || v_currentPow 1671033508415 - 1201280 + 1201310 false true @@ -41330,9 +41403,10 @@ public void f_operateFlexAssets(){ if (v instanceof J_EAConversionElektrolyser) { f_manageElektrolyser((J_EAConversionElektrolyser)v); } - if (v instanceof J_EAConversionCurtailer) { + //if (v instanceof J_EAConversionCurtailer) { // Must go last! - } /*else { + //} + /*else { v_currentPowerElectricity_kW += v.electricityConsumption_kW - v.electricityProduction_kW; v_conversionPowerElectric_kW += v.electricityConsumption_kW - v.electricityProduction_kW; v_currentPowerMethane_kW += v.methaneConsumption_kW - v.methaneProduction_kW; @@ -41359,13 +41433,7 @@ if (p_batteryAsset != null){ //v_batteryPowerElectric_kW = p_batteryAsset.electricityConsumption_kW - p_batteryAsset.electricityProduction_kW; //v_currentPowerElectricity_kW += v_batteryPowerElectric_kW; } - -// Operate curtailer. Must be the last asset to run!! - -if (p_curtailer != null){ - f_manageCurtailer(p_curtailer); - //v_currentPowerElectricity_kW += p_curtailer.electricityConsumption_kW; -}]]> +]]> VOID @@ -41417,31 +41485,6 @@ if (p_curtailer != null){ ElektrolyserAsset.f_updateAllFlows(elektrolyserSetpointElectric_kW/ElektrolyserAsset.getElectricCapacity_kW()); v_hydrogenProductionDeficit_kWh += ProductionSetpoint_kW - ElektrolyserAsset.hydrogenProduction_kW; // Update hydrogen production deficit -}]]> - - - VOID - - 1676965986339 - - 800503 - - false - true - true - - - - - 0) { - double curtailerSetpointElectric_kW = -min(0,v_currentPowerElectricity_kW + p_connectionCapacity_kW); - double[] flowsArray = CurtailerAsset.f_updateAllFlows(curtailerSetpointElectric_kW/CurtailerAsset.getElectricCapacity_kW()); - v_conversionPowerElectric_kW = flowsArray[4]; - //traceln("Curtailer setpoint in GC: %s is %s kW", this, curtailerSetpointElectric_kW); - /*if ( curtailerSetpointElectric_kW > 0 ) { - traceln("Windfarm is curtailing " + curtailerSetpointElectric_kW + " kW!"); - }*/ }]]> @@ -42552,9 +42595,10 @@ if (ElectrolyserAsset.getElectricCapacity_kW()>0) { if (v instanceof J_EAConversionElectrolyserAte) { f_manageElectrolyser((J_EAConversionElectrolyserAte)v); } - if (v instanceof J_EAConversionCurtailer) { + //if (v instanceof J_EAConversionCurtailer) { // Must go last! - } /*else { + //} + /*else { v_currentPowerElectricity_kW += v.electricityConsumption_kW - v.electricityProduction_kW; v_conversionPowerElectric_kW += v.electricityConsumption_kW - v.electricityProduction_kW; v_currentPowerMethane_kW += v.methaneConsumption_kW - v.methaneProduction_kW; @@ -42582,12 +42626,7 @@ if (p_batteryAsset != null){ //v_currentPowerElectricity_kW += v_batteryPowerElectric_kW; } -// Operate curtailer. Must be the last asset to run!! - -if (p_curtailer != null){ - f_manageCurtailer(p_curtailer); - //v_currentPowerElectricity_kW += p_curtailer.electricityConsumption_kW; -}]]> +]]> RETURNS_VALUE @@ -43749,7 +43788,7 @@ if (p_gasBuffer != null) { p_gasBuffer.f_updateAllFlows(p_gasBuffer.v_powerFraction_fr); } -if (p_curtailer != null) { +/*if (p_curtailer != null) { //traceln("Hello! " + CurtailerAsset.j_ea.getElectricCapacity_kW()); if (p_curtailer.getElectricCapacity_kW()>0) { double curtailerSetpointElectric_kW = 0.0; @@ -43759,12 +43798,8 @@ if (p_curtailer != null) { curtailerSetpointElectric_kW = -min(0,v_currentPowerElectricity_kW + p_connectionCapacity_kW); } p_curtailer.f_updateAllFlows(curtailerSetpointElectric_kW/p_curtailer.getElectricCapacity_kW()); - - /*if ( curtailerSetpointElectric_kW > 0 ) { - traceln("Windfarm is curtailing " + curtailerSetpointElectric_kW + " kW!"); - }*/ } -}]]> +}*/]]> VOID @@ -43827,8 +43862,8 @@ if (j_ea instanceof J_EAConversion) { ((J_EAConversionHeatPump)p_primaryHeatingAsset).outputTemperature_degC = 80; // For pastorizing milk } //traceln("heatingAsset class " + p_spaceHeatingAsset.getClass().toString()); - } else if (j_ea instanceof J_EAConversionCurtailer) { - p_curtailer = (J_EAConversionCurtailer)j_ea ; + //} else if (j_ea instanceof J_EAConversionCurtailer) { + // p_curtailer = (J_EAConversionCurtailer)j_ea ; } else { traceln("f_connectToChild in EnergyAsset: Exception! EnergyAsset " + j_ea + " is of unknown type or null! "); } @@ -44246,11 +44281,7 @@ traceln("NetConnection connecting to " + numberOfEnergyAssets + " EnergyAssets") //v_currentPowerElectricity_kW += v_batteryPowerElectric_kW; } } - -if (p_curtailer != null){ - f_manageCurtailer(p_curtailer); - //v_currentPowerElectricity_kW += p_curtailer.electricityConsumption_kW; -}]]> +]]> VOID @@ -46965,9 +46996,6 @@ public void f_operateFixedAssets(){ - - - false @@ -47478,6 +47506,9 @@ public void f_operateFlexAssets(){ + + + false @@ -47815,7 +47846,7 @@ public class J_EAProduction extends zero_engine.J_EA implements Serializable { public double getCapacityElectric_kW() { return this.capacityElectric_kW; } - + @Override public double[] operate(double ratioOfCapacity) { this.electricityProduction_kW = ratioOfCapacity * capacityElectric_kW; @@ -47832,6 +47863,22 @@ public class J_EAProduction extends zero_engine.J_EA implements Serializable { return returnEnergyFlows(); } + public double[] curtailElectricityProduction(double curtailmentSetpoint_kW) { + double currentElectricityProduction_kW = lastFlowsArray[0]; + double curtailmentPower_kW = max(0,min(currentElectricityProduction_kW, curtailmentSetpoint_kW)); + double[] arr = {-curtailmentPower_kW, 0, 0, 0, 0, 0, 0, 0, 0, curtailmentPower_kW}; + lastFlowsArray[0] -= curtailmentPower_kW; + lastFlowsArray[9] += curtailmentPower_kW; + //traceln("Electricity production of asset %s curtailed by %s kW!", this, curtailmentPower_kW); + if (parentAgent instanceof GridConnection) { + ((GridConnection)parentAgent).f_addFlows(arr, this); + } + if (ui_energyAsset!= null) { + ui_energyAsset.f_addFlows(arr); + } + return arr; + } + @Override public String toString() { return @@ -48224,7 +48271,7 @@ public class J_EA implements Cloneable { double[] arr = {electricityProduction_kW, methaneProduction_kW, hydrogenProduction_kW, heatProduction_kW, electricityConsumption_kW, methaneConsumption_kW, hydrogenConsumption_kW, heatConsumption_kW, dieselConsumption_kW, energyUse_kW }; return arr; } - + public double getCurrentStateOfCharge() { return 0; } diff --git a/database/db.properties b/database/db.properties index 9ec3d8d..af3a840 100644 --- a/database/db.properties +++ b/database/db.properties @@ -1,5 +1,5 @@ #HSQL Database Engine 2.7.1 -#Mon Jul 08 09:57:20 CEST 2024 -tx_timestamp=13565406 +#Mon Jul 08 16:41:06 CEST 2024 +tx_timestamp=13566800 modified=no version=2.7.1 diff --git a/database/db.script b/database/db.script index b016da0..3831831 100644 --- a/database/db.script +++ b/database/db.script @@ -29,7 +29,7 @@ SET FILES NIO TRUE SET FILES NIO SIZE 256 SET FILES LOG TRUE SET FILES LOG SIZE 50 -SET FILES CHECK 13565406 +SET FILES CHECK 13566800 SET DATABASE COLLATION "SQL_TEXT" PAD SPACE CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e' ALTER USER SA SET LOCAL TRUE