From dfe1caae5b27fc07e8d9f59a2abc61e621e7e6fc Mon Sep 17 00:00:00 2001 From: Luc-Sol Date: Fri, 20 Mar 2026 12:04:30 +0100 Subject: [PATCH] GC Now resets all its classes itself and cleanup of triptracker - EnergyModel no longer stores/reset/restores states of J_EAs and ActivityTrackers, these are now called through the GCs store/reset/restore state functions. - Removed the v_ from variable names in the TripTracker/CookingTracker. - Added some descriptions to the methods of the TripTracker - Removed old code/comments from TripTracker - Fixed indentation in the TripTracker --- _alp/Agents/EnergyModel/Code/Functions.java | 47 +-- .../Agents/GridConnection/Code/Functions.java | 32 +- _alp/Agents/GridConnection/Code/Functions.xml | 5 + _alp/Classes/Class.J_ActivityTracker.java | 10 +- .../Class.J_ActivityTrackerCooking.java | 72 ++--- .../Classes/Class.J_ActivityTrackerTrips.java | 276 +++++++++--------- 6 files changed, 206 insertions(+), 236 deletions(-) diff --git a/_alp/Agents/EnergyModel/Code/Functions.java b/_alp/Agents/EnergyModel/Code/Functions.java index 8b4701d..12d879b 100644 --- a/_alp/Agents/EnergyModel/Code/Functions.java +++ b/_alp/Agents/EnergyModel/Code/Functions.java @@ -237,11 +237,6 @@ p_timeVariables.updateTimeVariables(v_timeStepsElapsed, p_timeParameters); //// Store and reset model states -for (J_EA EA : c_energyAssets) { - EA.storeStatesAndReset(); -} - - for (GridConnection GC : c_gridConnections) { if (GC.v_rapidRunData != null) { @@ -255,21 +250,12 @@ GC.v_rapidRunData.connectionMetaData = GC.v_liveConnectionMetaData.getClone(); GC.v_rapidRunData.initializeAccumulators(GC.v_liveData.activeEnergyCarriers, GC.v_liveData.activeConsumptionEnergyCarriers, GC.v_liveData.activeProductionEnergyCarriers, GC.v_liveAssetsMetaData.activeAssetFlows); //f_initializeAccumulators(); - GC.f_resetStates(); + // f_resetStates resets the accumulators in rapidrundata, so must be after copying the previous run data + GC.f_resetStates(p_timeVariables); - GC.c_tripTrackers.forEach(tt->{ - tt.storeStatesAndReset(); - tt.setStartIndex(p_timeVariables, GC.f_getChargePoint()); - //tt.prepareNextActivity(p_runStartTime_h*60, GC.f_getChargePoint()); - }); - if (GC instanceof GCHouse) { - if (((GCHouse)GC).p_cookingTracker != null) { - ((GCHouse)GC).p_cookingTracker.storeStatesAndReset(); - } - } } for (GridConnection GC : c_subGridConnections) { - GC.f_resetStates(); + GC.f_resetStates(p_timeVariables); } for (GridNode GN : pop_gridNodes) { @@ -285,19 +271,11 @@ if (b_storePreviousRapidRunData) { EC.v_previousRunData = EC.v_rapidRunData; } - /*EC.v_rapidRunData.assetsMetaData = EC.v_liveAssetsMetaData.getClone(); - EC.v_rapidRunData.connectionMetaData = EC.v_liveConnectionMetaData.getClone(); - if(EC.v_rapidRunData.getStoreTotalAssetFlows() == false){ - EC.v_rapidRunData.setStoreTotalAssetFlows(true); - EC.v_rapidRunData.initializeAccumulators(p_runEndTime_h - p_runStartTime_h, p_timeStep_h, EC.v_liveData.activeEnergyCarriers, EC.v_liveData.activeConsumptionEnergyCarriers, EC.v_liveData.activeProductionEnergyCarriers, EC.v_liveAssetsMetaData.activeAssetFlows); - }*/ } EC.v_rapidRunData = new J_RapidRunData(p_timeParameters, true); EC.v_rapidRunData.assetsMetaData = EC.v_liveAssetsMetaData.getClone(); EC.v_rapidRunData.connectionMetaData = EC.v_liveConnectionMetaData.getClone(); - //if(EC.v_rapidRunData.getStoreTotalAssetFlows() == false){ EC.v_rapidRunData.setStoreTotalAssetFlows(true); - //} EC.v_rapidRunData.initializeAccumulators(EC.v_liveData.activeEnergyCarriers, EC.v_liveData.activeConsumptionEnergyCarriers, EC.v_liveData.activeProductionEnergyCarriers, EC.v_liveAssetsMetaData.activeAssetFlows); EC.f_resetStates(); @@ -379,27 +357,8 @@ v_timeStepsElapsed = v_timeStepsElapsed_live; p_timeVariables.updateTimeVariables(v_timeStepsElapsed, p_timeParameters); - -for (J_EA EA : c_energyAssets) { - EA.restoreStates(); -} - -/*for (GridNode GN : pop_gridNodes) { - //Has no reset states -}*/ - for (GridConnection GC : c_gridConnections) { GC.f_resetStatesAfterRapidRun(); - GC.c_tripTrackers.forEach(tt->{ - tt.restoreStates(); - //tt.prepareNextActivity((t_h-p_runStartTime_h)*60, GC.f_getChargePoint()); - }); - //GC.c_tripTrackers.forEach(tt->tt.prepareNextActivity((t_h-p_runStartTime_h)*60)); - if (GC instanceof GCHouse) { - if (((GCHouse)GC).p_cookingTracker != null) { - ((GCHouse)GC).p_cookingTracker.restoreStates(); - } - } } v_isRapidRun = false; diff --git a/_alp/Agents/GridConnection/Code/Functions.java b/_alp/Agents/GridConnection/Code/Functions.java index 20dfc03..bd39480 100644 --- a/_alp/Agents/GridConnection/Code/Functions.java +++ b/_alp/Agents/GridConnection/Code/Functions.java @@ -123,34 +123,43 @@ /*ALCODEEND*/} -double f_resetStates() +double f_resetStates(J_TimeVariables timeVariables) {/*ALCODESTART::1668983912731*/ fm_currentProductionFlows_kW.clear(); fm_currentConsumptionFlows_kW.clear(); fm_currentBalanceFlows_kW.clear(); fm_heatFromEnergyCarrier_kW.clear(); fm_consumptionForHeating_kW.clear(); -//fm_currentAssetFlows_kW.clear(); // Why not this one?? +//fm_currentAssetFlows_kW.clear(); // Why not this one?? (I'd have to check, but all these fm's are reset at calculateEnergyBalance, so they possibly could all be removed, ~Luc 20/03/26) v_previousPowerElectricity_kW = 0; v_previousPowerHeat_kW = 0; -//v_electricityPriceLowPassed_eurpkWh = 0; -//v_currentElectricityPriceConsumption_eurpkWh = 0; v_rapidRunData.resetAccumulators(v_liveData.activeEnergyCarriers, v_liveData.activeConsumptionEnergyCarriers, v_liveData.activeProductionEnergyCarriers); //f_initializeAccumulators(); //Reset specific variables/collections in specific GC types (GCProduction, GConversion, etc.) f_resetSpecificGCStates(); -//Store states and reset EMS +// Reset other classes if(p_energyManagement != null){ p_energyManagement.storeStatesAndReset(); } -//Store states and reset charge point if(p_chargePoint != null){ p_chargePoint.storeStatesAndReset(); } + +c_energyAssets.forEach(ea -> ea.storeStatesAndReset()); + +c_tripTrackers.forEach(tt -> { + tt.storeStatesAndReset(); + tt.setStartIndex(timeVariables, f_getChargePoint()); + } +); + +if (p_cookingTracker != null) { + p_cookingTracker.storeStatesAndReset(); +} /*ALCODEEND*/} double f_setOperatingSwitches() @@ -321,7 +330,7 @@ else if(j_ea instanceof J_EAFlex j_eaFlex){ double f_resetSpecificGCStates() {/*ALCODESTART::1717060111619*/ - +// to be overwritten by child GCs! /*ALCODEEND*/} double f_resetStatesAfterRapidRun() @@ -329,17 +338,22 @@ else if(j_ea instanceof J_EAFlex j_eaFlex){ //Reset specificGC states after rapid run f_resetSpecificGCStatesAfterRapidRun(); -//Restore states in EMS +//Restore other classes if(p_energyManagement != null){ p_energyManagement.restoreStates(); } -//Restore states in charge point if(p_chargePoint != null){ p_chargePoint.restoreStates(); } +c_energyAssets.forEach(ea -> ea.restoreStates()); +c_tripTrackers.forEach(tt-> tt.restoreStates()); + +if (p_cookingTracker != null) { + p_cookingTracker.restoreStates(); +} /*ALCODEEND*/} double f_resetSpecificGCStatesAfterRapidRun() diff --git a/_alp/Agents/GridConnection/Code/Functions.xml b/_alp/Agents/GridConnection/Code/Functions.xml index 4c6b2d3..d0c4b7f 100644 --- a/_alp/Agents/GridConnection/Code/Functions.xml +++ b/_alp/Agents/GridConnection/Code/Functions.xml @@ -118,6 +118,10 @@ false true true + + + + @@ -238,6 +242,7 @@ false true true + VOID diff --git a/_alp/Classes/Class.J_ActivityTracker.java b/_alp/Classes/Class.J_ActivityTracker.java index 9afbc06..6e24db7 100644 --- a/_alp/Classes/Class.J_ActivityTracker.java +++ b/_alp/Classes/Class.J_ActivityTracker.java @@ -24,8 +24,8 @@ public abstract class J_ActivityTracker implements I_StoreStatesAndReset { protected ArrayList endtimes_min = new ArrayList<>(); //private ArrayList eventMagnitude = new ArrayList<>(); public int nbActivities = 0; - public int v_eventIndex = 0; - protected int v_eventIndexStored =0; + public int eventIndex = 0; + protected int eventIndexStored =0; /** * Default constructor @@ -37,12 +37,12 @@ public J_ActivityTracker(EnergyModel main, int rowIndex, double time_min) { } public void storeStatesAndReset() { - v_eventIndexStored = v_eventIndex; - v_eventIndex = 0; + eventIndexStored = eventIndex; + eventIndex = 0; } public void restoreStates() { - v_eventIndex = v_eventIndexStored; + eventIndex = eventIndexStored; } diff --git a/_alp/Classes/Class.J_ActivityTrackerCooking.java b/_alp/Classes/Class.J_ActivityTrackerCooking.java index 5def17b..d91c686 100644 --- a/_alp/Classes/Class.J_ActivityTrackerCooking.java +++ b/_alp/Classes/Class.J_ActivityTrackerCooking.java @@ -54,12 +54,12 @@ public J_ActivityTrackerCooking(TextFile inputCookingActivities, int rowIndex, d powerFractions_fr.add(ratio); } - while ( starttimes_min.get(v_eventIndex) - time_min < 0) { - starttimes_min.set( v_eventIndex, starttimes_min.get(v_eventIndex) + 1440 ); // Source data is always just one day, repeating every day. - endtimes_min.set( v_eventIndex, endtimes_min.get(v_eventIndex) + 1440 ); // Source data is always just one day, repeating every day. - v_eventIndex++; - if ( v_eventIndex > starttimes_min.size() - 1 ) { - v_eventIndex = 0; + while ( starttimes_min.get(eventIndex) - time_min < 0) { + starttimes_min.set( eventIndex, starttimes_min.get(eventIndex) + 1440 ); // Source data is always just one day, repeating every day. + endtimes_min.set( eventIndex, endtimes_min.get(eventIndex) + 1440 ); // Source data is always just one day, repeating every day. + eventIndex++; + if ( eventIndex > starttimes_min.size() - 1 ) { + eventIndex = 0; } } @@ -73,62 +73,62 @@ public J_ActivityTrackerCooking(TextFile inputCookingActivities, int rowIndex, d public void manageActivities(J_TimeVariables timeVariables) { double time_min = timeVariables.getAnyLogicTime_h() * 60; //traceln("Cooking tracker current time: " + time_min); - //traceln("Event index: " + v_eventIndex); + //traceln("Event index: " + eventIndex); //traceln("startTimes: " + starttimes_min); //traceln("endTimes: " + endtimes_min); //traceln("powerFractions_fr: " + powerFractions_fr); if (cooking) { - if (time_min >= endtimes_min.get(v_eventIndex) ) { // end cooking session. Also check if a new one starts in this timestep! + if (time_min >= endtimes_min.get(eventIndex) ) { // end cooking session. Also check if a new one starts in this timestep! //main.v_activeCookingSessions.decrementAndGet(); //traceln("End of cooking session, currently active cooking sessions %s", main.v_activeCookingSessions); // factor to compensate for the fact that you might not be cooking for the entire timestep. - double fr = (time_min - this.endtimes_min.get(this.v_eventIndex)) / this.timeStep_min; - this.powerFraction_fr = fr * this.powerFractions_fr.get(this.v_eventIndex); + double fr = (time_min - this.endtimes_min.get(this.eventIndex)) / this.timeStep_min; + this.powerFraction_fr = fr * this.powerFractions_fr.get(this.eventIndex); - starttimes_min.set( v_eventIndex, starttimes_min.get(v_eventIndex) + 1440 ); - endtimes_min.set( v_eventIndex, endtimes_min.get(v_eventIndex) + 1440 ); - v_eventIndex++; - if ( v_eventIndex >= starttimes_min.size() ) { - v_eventIndex = 0; + starttimes_min.set( eventIndex, starttimes_min.get(eventIndex) + 1440 ); + endtimes_min.set( eventIndex, endtimes_min.get(eventIndex) + 1440 ); + eventIndex++; + if ( eventIndex >= starttimes_min.size() ) { + eventIndex = 0; } cooking=false; - if (time_min >= starttimes_min.get(v_eventIndex)) { + if (time_min >= starttimes_min.get(eventIndex)) { // factor to compensate for the fact that you might not be cooking for the entire timestep. - fr = (time_min - this.starttimes_min.get(this.v_eventIndex)) / this.timeStep_min; - this.powerFraction_fr = fr * this.powerFractions_fr.get(this.v_eventIndex); + fr = (time_min - this.starttimes_min.get(this.eventIndex)) / this.timeStep_min; + this.powerFraction_fr = fr * this.powerFractions_fr.get(this.eventIndex); //main.v_activeCookingSessions.incrementAndGet(); cooking=true; - traceln("Starting next cooking session in same timestep as previous session ended!! Rowindex %s, eventIndex %s\", rowIndex, v_eventIndex"); + traceln("Starting next cooking session in same timestep as previous session ended!! Rowindex %s, eventIndex %s\", rowIndex, eventIndex"); } } else { - this.powerFraction_fr = this.starttimes_min.get(this.v_eventIndex); + this.powerFraction_fr = this.starttimes_min.get(this.eventIndex); } - } else if (time_min >= starttimes_min.get(v_eventIndex) ) { // start cooking session. Also check if it ends within this timestep! - /*if (endtimes_min.get(v_eventIndex) - starttimes_min.get(v_eventIndex) > 100) { - traceln("Cooking event longer than 100 minutes!! Rowindex %s, eventIndex %s.", rowIndex, v_eventIndex); + } else if (time_min >= starttimes_min.get(eventIndex) ) { // start cooking session. Also check if it ends within this timestep! + /*if (endtimes_min.get(eventIndex) - starttimes_min.get(eventIndex) > 100) { + traceln("Cooking event longer than 100 minutes!! Rowindex %s, eventIndex %s.", rowIndex, eventIndex); }*/ // factor to compensate for the fact that you might not be cooking for the entire timestep. - double fr = (time_min - this.starttimes_min.get(this.v_eventIndex)) / this.timeStep_min; - this.powerFraction_fr = fr * this.powerFractions_fr.get(this.v_eventIndex); + double fr = (time_min - this.starttimes_min.get(this.eventIndex)) / this.timeStep_min; + this.powerFraction_fr = fr * this.powerFractions_fr.get(this.eventIndex); //main.v_activeCookingSessions.incrementAndGet(); cooking=true; - if (time_min >= endtimes_min.get(v_eventIndex) ) { // end cooking session in the same timestep? Still need to fix energy use for this case!! + if (time_min >= endtimes_min.get(eventIndex) ) { // end cooking session in the same timestep? Still need to fix energy use for this case!! //main.v_activeCookingSessions.decrementAndGet(); //traceln("End of cooking session, currently active cooking sessions %s", main.v_activeCookingSessions); - fr = (this.endtimes_min.get(this.v_eventIndex) - this.starttimes_min.get(this.v_eventIndex)) / this.timeStep_min; - this.powerFraction_fr = fr * this.powerFractions_fr.get(this.v_eventIndex); + fr = (this.endtimes_min.get(this.eventIndex) - this.starttimes_min.get(this.eventIndex)) / this.timeStep_min; + this.powerFraction_fr = fr * this.powerFractions_fr.get(this.eventIndex); - starttimes_min.set( v_eventIndex, starttimes_min.get(v_eventIndex) + 1440 ); - endtimes_min.set( v_eventIndex, endtimes_min.get(v_eventIndex) + 1440 ); - v_eventIndex++; - if ( v_eventIndex >= starttimes_min.size() ) { - v_eventIndex = 0; + starttimes_min.set( eventIndex, starttimes_min.get(eventIndex) + 1440 ); + endtimes_min.set( eventIndex, endtimes_min.get(eventIndex) + 1440 ); + eventIndex++; + if ( eventIndex >= starttimes_min.size() ) { + eventIndex = 0; } cooking=false; } @@ -142,17 +142,17 @@ public void manageActivities(J_TimeVariables timeVariables) { @Override public void storeStatesAndReset() { - v_eventIndexStored = v_eventIndex; + eventIndexStored = eventIndex; storedStarttimes_min = new ArrayList<>(starttimes_min); storedEndtimes_min = new ArrayList<>(endtimes_min); starttimes_min = new ArrayList<>(initalStarttimes_min); endtimes_min = new ArrayList<>(initalEndtimes_min); - v_eventIndex = 0; + eventIndex = 0; } @Override public void restoreStates() { - v_eventIndex = v_eventIndexStored; + eventIndex = eventIndexStored; starttimes_min = new ArrayList<>(storedStarttimes_min); endtimes_min = new ArrayList<>(storedEndtimes_min); } diff --git a/_alp/Classes/Class.J_ActivityTrackerTrips.java b/_alp/Classes/Class.J_ActivityTrackerTrips.java index 13d2d68..359ba8f 100644 --- a/_alp/Classes/Class.J_ActivityTrackerTrips.java +++ b/_alp/Classes/Class.J_ActivityTrackerTrips.java @@ -12,16 +12,13 @@ public class J_ActivityTrackerTrips extends J_ActivityTracker { public ArrayList distances_km = new ArrayList<>(); private int rowIndex; public I_Vehicle vehicle; - public double v_idleTimeToNextTrip_min; - public double v_idleTimeToNextTripStored_min; - public double v_tripDist_km; - //public double v_energyNeedForNextTrip_kWh; - //public double v_energyNeedForNextTripStored_kWh; - public double v_nextEventStartTime_min; + public double idleTimeToNextTrip_min; + public double idleTimeToNextTripStored_min; + public double tripDistance_km; + public double nextEventStartTime_min; public double distanceScaling_fr = 1.0; public double currentTripTimesteps_n; private double nextEventStartTime_h; - //public String tripPatternIdentifier; /** * Default constructor @@ -36,7 +33,6 @@ public J_ActivityTrackerTrips(J_TimeParameters timeParameters, TextFile tripsCsv tripsCsv.close(); tripsCsv.canReadMore(); - tripsCsv.readLine(); // Skips first line while (roundToInt(tripsCsv.readDouble())!=rowIndex && tripsCsv.canReadMore()) { // Skip until rowIndex found @@ -54,19 +50,19 @@ public J_ActivityTrackerTrips(J_TimeParameters timeParameters, TextFile tripsCsv distances_km.add(tripsCsv.readDouble()); } - // 'forward' to next current activity + // 'forward' to next activity setStartIndex(timeVariables, chargePointRegistration); } private double getTimeSinceWeekStart(double time_min) { - double timeSinceWeekStart_min = (time_min + (timeParameters.getDayOfWeek1jan()-1) * 24 * 60) % (7*24*60); // Trip start/end-times are all defined as minutes since monday 00:00h + double timeSinceWeekStart_min = (time_min + (timeParameters.getDayOfWeek1jan()-1) * 24 * 60) % (7*24*60); return timeSinceWeekStart_min; } private void setNextTrip() { - v_eventIndex++; - if ( v_eventIndex > starttimes_min.size() - 1 ) { - v_eventIndex = 0; + eventIndex++; + if ( eventIndex > starttimes_min.size() - 1 ) { + eventIndex = 0; } } @@ -87,10 +83,8 @@ public void setAnnualDistance_km(double desiredAnnualDistance_km) { // Scale tri double currentAnnualDistance_km = getAnnualDistance_km(); double scalingFactor_f = desiredAnnualDistance_km / currentAnnualDistance_km; - //distances_km = (ArrayList)distances_km.stream().map(a -> scalingFactor_f*a).toList(); ListIterator iterator = distances_km.listIterator(); for (int i = 0; i= starttimes_min.get(v_eventIndex) && (timeSinceWeekStart_min-timeParameters.getTimeStep_h() * 60) < starttimes_min.get(v_eventIndex)) { // is a trip starting this timestep? - //currentTripDuration = roundToInt(endtimes_min.get(v_eventIndex) - starttimes_min.get(v_eventIndex) / (energyModel.p_timeStep_h * 60)); - currentTripTimesteps_n = max(1,roundToInt(((endtimes_min.get(v_eventIndex) - starttimes_min.get(v_eventIndex)) / (timeParameters.getTimeStep_h() * 60)))); - - vehicle.startTrip(timeVariables); - if(vehicle instanceof J_EAEV EV) { - chargePointRegistration.deregisterChargingRequest(EV); - } - //if (time_min == roundToInt(endtimes_min.get(v_eventIndex) / (60*energyModel.p_timeStep_h)) * (energyModel.p_timeStep_h*60) ) { // is the trip also ending this timestep? - if (timeSinceWeekStart_min >= endtimes_min.get(v_eventIndex) && (timeSinceWeekStart_min-timeParameters.getTimeStep_h() * 60) < endtimes_min.get(v_eventIndex)) { // is the trip also ending this timestep? - vehicle.endTrip(v_tripDist_km); - setNextTrip();//v_eventIndex++; - prepareNextActivity(time_min, chargePointRegistration); - } - } - } else { - if (vehicle instanceof J_EAFuelVehicle fuelVehicle) { - fuelVehicle.progressTrip(v_tripDist_km / currentTripTimesteps_n); - } - //if (time_min == roundToInt(endtimes_min.get(v_eventIndex)/ (60*energyModel.p_timeStep_h)) * 60*energyModel.p_timeStep_h ) { // is a trip ending this timestep? - if (timeSinceWeekStart_min >= endtimes_min.get(v_eventIndex) && (timeSinceWeekStart_min-timeParameters.getTimeStep_h() * 60) < endtimes_min.get(v_eventIndex)) { // is a trip ending this timestep? - vehicle.endTrip(v_tripDist_km); - setNextTrip();//v_eventIndex++; - prepareNextActivity(time_min, chargePointRegistration); - //if (time_min == roundToInt(starttimes_min.get(v_eventIndex) / (60*energyModel.p_timeStep_h)) * (energyModel.p_timeStep_h*60) ) { // is the next trip also starting this timestep? - if (timeSinceWeekStart_min >= starttimes_min.get(v_eventIndex) && (timeSinceWeekStart_min-timeParameters.getTimeStep_h() * 60) < starttimes_min.get(v_eventIndex) ) { // is the next trip also starting this timestep? - currentTripTimesteps_n = max(1,roundToInt(((endtimes_min.get(v_eventIndex) - starttimes_min.get(v_eventIndex)) / (timeParameters.getTimeStep_h() * 60)))); - vehicle.startTrip(timeVariables); - if(vehicle instanceof J_EAEV EV) { - chargePointRegistration.deregisterChargingRequest(EV); - } - } - } - } - } + double time_min = timeVariables.getT_h() * 60; + double timeSinceWeekStart_min = getTimeSinceWeekStart(time_min); // Trip start/end-times are all defined as minutes since monday 00:00h, trips are looped indefinitely + if (vehicle.getAvailability()) { // at start of timestep! check for multiple 'events' in timestep! + if ( timeSinceWeekStart_min >= starttimes_min.get(eventIndex) && (timeSinceWeekStart_min-timeParameters.getTimeStep_h() * 60) < starttimes_min.get(eventIndex)) { // is a trip starting this timestep? + currentTripTimesteps_n = max(1,roundToInt(((endtimes_min.get(eventIndex) - starttimes_min.get(eventIndex)) / (timeParameters.getTimeStep_h() * 60)))); + + vehicle.startTrip(timeVariables); + if(vehicle instanceof J_EAEV EV) { + chargePointRegistration.deregisterChargingRequest(EV); + } + if (timeSinceWeekStart_min >= endtimes_min.get(eventIndex) && (timeSinceWeekStart_min-timeParameters.getTimeStep_h() * 60) < endtimes_min.get(eventIndex)) { // is the trip also ending this timestep? + vehicle.endTrip(tripDistance_km); + setNextTrip(); + prepareNextActivity(time_min, chargePointRegistration); + } + } + } else { + if (vehicle instanceof J_EAFuelVehicle fuelVehicle) { + fuelVehicle.progressTrip(tripDistance_km / currentTripTimesteps_n); + } + if (timeSinceWeekStart_min >= endtimes_min.get(eventIndex) && (timeSinceWeekStart_min-timeParameters.getTimeStep_h() * 60) < endtimes_min.get(eventIndex)) { // is a trip ending this timestep? + vehicle.endTrip(tripDistance_km); + setNextTrip(); + prepareNextActivity(time_min, chargePointRegistration); + if (timeSinceWeekStart_min >= starttimes_min.get(eventIndex) && (timeSinceWeekStart_min-timeParameters.getTimeStep_h() * 60) < starttimes_min.get(eventIndex) ) { // is the next trip also starting this timestep? + currentTripTimesteps_n = max(1,roundToInt(((endtimes_min.get(eventIndex) - starttimes_min.get(eventIndex)) / (timeParameters.getTimeStep_h() * 60)))); + vehicle.startTrip(timeVariables); + if(vehicle instanceof J_EAEV EV) { + chargePointRegistration.deregisterChargingRequest(EV); + } + } + } + } + } - public void setStartIndex(J_TimeVariables timeVariables, I_ChargePointRegistration chargePointRegistration) { - // 'forward' to current activity if tripTracker is instantiated not at the start of the simulation or year - double time_min = timeVariables.getT_h() * 60.0; - - double timeSinceWeekStart_min = getTimeSinceWeekStart(time_min); - boolean looped = false; - while ( starttimes_min.get(v_eventIndex) < (timeSinceWeekStart_min ) ) { // If this occurs 'during' a trip, that trip is ignored, it is not executed. - setNextTrip(); // Skip to the next trip. - - if (v_eventIndex == starttimes_min.size()-1 ) { - if (looped) { // break while loop! - setNextTrip(); // Reverts to first trip of week - break; - } else { - looped = true; - } - } - - } - prepareNextActivity(time_min, chargePointRegistration); - } - - public void prepareNextActivity(double time_min, I_ChargePointRegistration chargePointRegistration) { - /*if ( v_eventIndex >= starttimes_min.size() ) { // This should only happen at the end of the year, not every week. - v_eventIndex = 0; - }*/ - double timeSinceWeekStart_min = getTimeSinceWeekStart(time_min); - v_nextEventStartTime_min = starttimes_min.get(v_eventIndex); // minutes from start of week - - if (v_eventIndex == 0 && timeSinceWeekStart_min > v_nextEventStartTime_min) { // Next week's trip! - nextEventStartTime_h = (v_nextEventStartTime_min + time_min - timeSinceWeekStart_min)/60 + 168; - } else { - nextEventStartTime_h = (v_nextEventStartTime_min + time_min - timeSinceWeekStart_min)/60; - } - //traceln("Prepare next activity, trip startTime: %s hours. Time since week start: %s", nextEventStartTime_h, (timeSinceWeekStart_min)/60); - v_idleTimeToNextTrip_min = (v_nextEventStartTime_min - timeSinceWeekStart_min) % (24*7*60); // Modulo 24*7*60 needed because otherwise negative values can occur when trip starts 'next week'. - v_tripDist_km = distanceScaling_fr * distances_km.get( v_eventIndex ); // Update upcoming trip distance - - if (vehicle instanceof J_EAEV ev) { - - double energyNeedForNextTrip_kWh = ev.getEnergyConsumption_kWhpkm() * v_tripDist_km; - if (v_idleTimeToNextTrip_min > 0 && (energyNeedForNextTrip_kWh-ev.getCurrentSOC_kWh())> v_idleTimeToNextTrip_min/60 * ev.capacityElectric_kW) { - traceln("TripTracker reports: charging need for next trip is not feasible! Time till next trip: %s hours, chargeNeed_kWh: %s", roundToDecimal(v_idleTimeToNextTrip_min/60,2), roundToDecimal(energyNeedForNextTrip_kWh-ev.getCurrentSOC_kWh(),2)); - } - //v_energyNeedForNextTrip_kWh = min(v_energyNeedForNextTrip_kWh+10,ev.getStorageCapacity_kWh()); // added 10kWh margin 'just in case'. This is actually realistic; people will charge their cars a bit more than strictly needed for the next trip, if possible. - // Check if more charging is needed for next trip! - double nextTripDist_km = 0; - double nextTripStartTime_min = 0; - - if ( v_eventIndex == starttimes_min.size() - 1 ) { - nextTripDist_km = 0;//distances_km.get( 0 ); - nextTripStartTime_min = endtimes_min.get(v_eventIndex); - } else { - nextTripDist_km = distanceScaling_fr*distances_km.get( v_eventIndex+1 ); - nextTripStartTime_min = starttimes_min.get( v_eventIndex+1 ); - } - double additionalChargingNeededForNextTrip_kWh = max(0,nextTripDist_km * ev.getEnergyConsumption_kWhpkm() - (nextTripStartTime_min - endtimes_min.get(v_eventIndex))/60*ev.getVehicleChargingCapacity_kW()); - /*if (additionalChargingNeededForNextTrip_kWh>0) { - traceln("*******Additional charging required to prepare for trip after next trip!*********"); - }*/ - energyNeedForNextTrip_kWh += additionalChargingNeededForNextTrip_kWh; - energyNeedForNextTrip_kWh = min(energyNeedForNextTrip_kWh+10,ev.getStorageCapacity_kWh()); - //traceln("TripTracker, energyNeedForNextTrip: %s", v_energyNeedForNextTrip_kWh); - ev.setEnergyNeedForNextTrip_kWh(energyNeedForNextTrip_kWh); - /*if ( (v_energyNeedForNextTrip_kWh - EV.getCurrentStateOfCharge() * EV.getStorageCapacity_kWh()) / (v_idleTimeToNextTrip_min/60) > EV.capacityElectric_kW ) { - traceln("Infeasible trip pattern for EV, not enough time to charge for next trip! Required charging power is: " + (v_energyNeedForNextTrip_kWh - EV.getCurrentStateOfCharge() * EV.getStorageCapacity_kWh()) / (v_idleTimeToNextTrip_min/60) + " kW"); - traceln("RowIndex: " + rowIndex + " tripDistance: " + v_tripDist_km + " km, time to next trip: " + v_idleTimeToNextTrip_min + " minutes"); + /* + * This method 'Forwards' to the activity at time in timeVariables + * It also immediately calls prepareNextActivity + */ + public void setStartIndex(J_TimeVariables timeVariables, I_ChargePointRegistration chargePointRegistration) { + double time_min = timeVariables.getT_h() * 60.0; + double timeSinceWeekStart_min = getTimeSinceWeekStart(time_min); + boolean looped = false; + while ( starttimes_min.get(eventIndex) < (timeSinceWeekStart_min ) ) { // If this occurs 'during' a trip, that trip is ignored, it is not executed. + setNextTrip(); // Skip to the next trip. + + if (eventIndex == starttimes_min.size()-1 ) { + if (looped) { + setNextTrip(); // Increments eventIndex, reverts to first trip of week when 'overflowing' + break; + } else { + looped = true; + } + } + + } + prepareNextActivity(time_min, chargePointRegistration); + } + + /* + * This method is called after the previous trip ended. + * It calculates the time to and distance of the coming trip. + * If the vehicle is an EV it also calculates the charging need, including possible future trips. + * The function passes this information to the EV and registers the charging request at the chargepoint. + */ + public void prepareNextActivity(double time_min, I_ChargePointRegistration chargePointRegistration) { + // Trip start/end-times are all defined as minutes since monday 00:00h + double timeSinceWeekStart_min = getTimeSinceWeekStart(time_min); + nextEventStartTime_min = starttimes_min.get(eventIndex); + + if (eventIndex == 0 && timeSinceWeekStart_min > nextEventStartTime_min) { // Next week's trip! + nextEventStartTime_h = (nextEventStartTime_min + time_min - timeSinceWeekStart_min)/60 + 168; + } else { + nextEventStartTime_h = (nextEventStartTime_min + time_min - timeSinceWeekStart_min)/60; + } + // traceln("Prepare next activity, trip startTime: %s hours. Time since week start: %s", nextEventStartTime_h, (timeSinceWeekStart_min)/60); + idleTimeToNextTrip_min = (nextEventStartTime_min - timeSinceWeekStart_min) % (24*7*60); // Modulo 24*7*60 needed because otherwise negative values can occur when trip starts 'next week'. + tripDistance_km = distanceScaling_fr * distances_km.get( eventIndex ); // Update upcoming trip distance + + if (vehicle instanceof J_EAEV ev) { + + double energyNeedForNextTrip_kWh = ev.getEnergyConsumption_kWhpkm() * tripDistance_km; + if (idleTimeToNextTrip_min > 0 && (energyNeedForNextTrip_kWh-ev.getCurrentSOC_kWh())> idleTimeToNextTrip_min/60 * ev.capacityElectric_kW) { + traceln("TripTracker reports: charging need for next trip is not feasible! Time till next trip: %s hours, chargeNeed_kWh: %s", roundToDecimal(idleTimeToNextTrip_min/60,2), roundToDecimal(energyNeedForNextTrip_kWh-ev.getCurrentSOC_kWh(),2)); + } + //v_energyNeedForNextTrip_kWh = min(v_energyNeedForNextTrip_kWh+10,ev.getStorageCapacity_kWh()); // added 10kWh margin 'just in case'. This is actually realistic; people will charge their cars a bit more than strictly needed for the next trip, if possible. + // Check if more charging is needed for next trip! + double nextTripDist_km = 0; + double nextTripStartTime_min = 0; + + if ( eventIndex == starttimes_min.size() - 1 ) { + nextTripDist_km = 0;//distances_km.get( 0 ); + nextTripStartTime_min = endtimes_min.get(eventIndex); + } else { + nextTripDist_km = distanceScaling_fr*distances_km.get( eventIndex+1 ); + nextTripStartTime_min = starttimes_min.get( eventIndex+1 ); + } + double additionalChargingNeededForNextTrip_kWh = max(0,nextTripDist_km * ev.getEnergyConsumption_kWhpkm() - (nextTripStartTime_min - endtimes_min.get(eventIndex))/60*ev.getVehicleChargingCapacity_kW()); + + energyNeedForNextTrip_kWh += additionalChargingNeededForNextTrip_kWh; + energyNeedForNextTrip_kWh = min(energyNeedForNextTrip_kWh+10,ev.getStorageCapacity_kWh()); + //traceln("TripTracker, energyNeedForNextTrip: %s", v_energyNeedForNextTrip_kWh); + ev.setEnergyNeedForNextTrip_kWh(energyNeedForNextTrip_kWh); + /*if ( (v_energyNeedForNextTrip_kWh - EV.getCurrentStateOfCharge() * EV.getStorageCapacity_kWh()) / (idleTimeToNextTrip_min/60) > EV.capacityElectric_kW ) { + traceln("Infeasible trip pattern for EV, not enough time to charge for next trip! Required charging power is: " + (v_energyNeedForNextTrip_kWh - EV.getCurrentStateOfCharge() * EV.getStorageCapacity_kWh()) / (idleTimeToNextTrip_min/60) + " kW"); + traceln("RowIndex: " + rowIndex + " tripDistance: " + tripDistance_km + " km, time to next trip: " + idleTimeToNextTrip_min + " minutes"); } */ - - //Register EV at the chargepoint - chargePointRegistration.registerChargingRequest(ev); - } - } + + //Register EV at the chargepoint + chargePointRegistration.registerChargingRequest(ev); + } + } public double getNextEventStartTime_h() { return nextEventStartTime_h; @@ -231,25 +231,17 @@ public double getDistanceScaling_fr( ) { @Override public void storeStatesAndReset() { - v_eventIndexStored = v_eventIndex; - //v_energyNeedForNextTripStored_kWh = v_energyNeedForNextTrip_kWh; - v_idleTimeToNextTripStored_min = v_idleTimeToNextTrip_min; - //v_eventIndex = 0; Taken care of by setStartIndex() call! - //v_energyNeedForNextTrip_kWh = 0; - v_idleTimeToNextTrip_min = 0; + eventIndexStored = eventIndex; + idleTimeToNextTripStored_min = idleTimeToNextTrip_min; + idleTimeToNextTrip_min = 0; + // Don't forget to call setStartIndex ! } @Override public void restoreStates() { - v_eventIndex = v_eventIndexStored; - v_nextEventStartTime_min = starttimes_min.get(v_eventIndex); - v_idleTimeToNextTrip_min = v_idleTimeToNextTripStored_min; - v_tripDist_km = distanceScaling_fr * distances_km.get( v_eventIndex ); // Update upcoming trip distance - - /* - v_energyNeedForNextTrip_kWh = v_energyNeedForNextTripStored_kWh; - if(vehicle instanceof J_EAEV ev) { - ev.setEnergyNeedForNextTrip_kWh(v_energyNeedForNextTrip_kWh); - }*/ + eventIndex = eventIndexStored; + nextEventStartTime_min = starttimes_min.get(eventIndex); + idleTimeToNextTrip_min = idleTimeToNextTripStored_min; + tripDistance_km = distanceScaling_fr * distances_km.get( eventIndex ); // Update upcoming trip distance } }