diff --git a/Zero_engine.alpx b/Zero_engine.alpx index 0ffa0b8a..8559d95b 100644 --- a/Zero_engine.alpx +++ b/Zero_engine.alpx @@ -1,7 +1,7 @@ 1658477103134 @@ -1450,6 +1450,10 @@ 1737025326025 + + 1737633433233 + + com.anylogic.libraries.modules.markup_descriptors diff --git a/_alp/Agents/EnergyModel/Code/Functions.java b/_alp/Agents/EnergyModel/Code/Functions.java index f9d2134f..334f088d 100644 --- a/_alp/Agents/EnergyModel/Code/Functions.java +++ b/_alp/Agents/EnergyModel/Code/Functions.java @@ -1061,7 +1061,7 @@ null, roundToDecimal( a.v_electricityImported_kWh-a.v_electricityExported_kWh, 2 int v_timeStepsElapsed_live = v_timeStepsElapsed; v_timeStepsElapsed=0; -c_profiles.forEach(p -> p.updateValue(p_runStartTime_h)); +c_profiles.forEach(p -> p.updateValue(p_runStartTime_h)); c_forecasts.forEach(p -> p.initializeForecast(p_runStartTime_h)); //c_forecasts.parallelStream().forEach(p -> p.initializeForecast(p_runStartTime_h)); diff --git a/_alp/Agents/GridConnection/Code/Functions.java b/_alp/Agents/GridConnection/Code/Functions.java index 46315081..e2f39206 100644 --- a/_alp/Agents/GridConnection/Code/Functions.java +++ b/_alp/Agents/GridConnection/Code/Functions.java @@ -14,8 +14,8 @@ //p_parentNodeHeat = myParentNodeHeat; } -if (p_ownerID!=null){ - ConnectionOwner myParentConnectionOwner = findFirst(energyModel.pop_connectionOwners, p->p.p_actorID.equals(p_ownerID)) ; +if (p_owner!=null){ + ConnectionOwner myParentConnectionOwner = p_owner; //findFirst(energyModel.pop_connectionOwners, p->p.p_actorID.equals(p_ownerID)) ; if( myParentConnectionOwner instanceof ConnectionOwner) { //p_ownerActor = myParentConnectionOwner; l_ownerActor.connectTo(myParentConnectionOwner); @@ -408,7 +408,6 @@ else if (j_ea instanceof J_EAConversionCurtailer || j_ea instanceof J_EAConversi c_consumptionAssets.forEach(c -> c.f_updateAllFlows(0)); c_productionAssets.forEach(p -> p.f_updateAllFlows(0)); c_profileAssets.forEach(p -> p.f_updateAllFlows(energyModel.t_h)); - /*ALCODEEND*/} double f_resetStates() @@ -1242,6 +1241,8 @@ else if (j_ea.energyAssetType == OL_EnergyAssetType.CHP) { } else { traceln( "Unrecognized profile type!"); } +} else if (j_ea instanceof J_EADieselTractor) { + c_profileAssets.add(j_ea); } else { traceln("Unrecognized energy asset %s in gridconnection %s", j_ea, this); } diff --git a/_alp/Agents/GridConnection/Variables.xml b/_alp/Agents/GridConnection/Variables.xml index 999d76a9..e157c341 100644 --- a/_alp/Agents/GridConnection/Variables.xml +++ b/_alp/Agents/GridConnection/Variables.xml @@ -5875,7 +5875,7 @@ true ArrayList - J_EAProfile + J_EA String diff --git a/_alp/Classes/Class.J_EADieselTractor.java b/_alp/Classes/Class.J_EADieselTractor.java new file mode 100644 index 00000000..ce3c44a8 --- /dev/null +++ b/_alp/Classes/Class.J_EADieselTractor.java @@ -0,0 +1,120 @@ +import java.util.*; + +public class J_EADieselTractor extends J_EA implements Serializable { + final static double DIESEL_ENERGY_DENSITY_KWH_PER_L = 9.7; + + final double[] dieselConsumptionPerWeek_L; + final double workDayStart_h = 6; + final double workDayEnd_h = 17; + + /** + * @param parentAgent + * @param yearlyDieselConsumption_l diesel consumption of a single tractor for a whole year + * @param dieselConsumptionPerWeek profile of a year of diesel consumption. + * Usually expressed in L per ha per week for a specific crop or mix of crops. + * For our purpose the unit doesn't matter. + * @param timeStep_h + */ + public J_EADieselTractor(Agent parentAgent, double yearlyDieselConsumption_L, double[] dieselConsumptionPerWeek, double timeStep_h) { + if (parentAgent == null) { + throw new RuntimeException("Diesel tractor missing parent agent"); + } + + if (yearlyDieselConsumption_L <= 100.0) { + throw new RuntimeException( + String.format("Diesel tractor fuel usage conspicuously low: %d L", yearlyDieselConsumption_L) + ); + } + + if (dieselConsumptionPerWeek == null) { + throw new RuntimeException("Tractor diesel consumption profile is null"); + } + + if (dieselConsumptionPerWeek.length != 52) { + throw new RuntimeException( + String.format("Tractor diesel consumption profile has %d weeks instead of 52", dieselConsumptionPerWeek.length) + ); + } + + if (timeStep_h <= 0.0) { + throw new RuntimeException("Tractor timestep is off"); + } + + this.parentAgent = parentAgent; + this.dieselConsumptionPerWeek_L = calculateDieselConsumptionPerWeek_L(yearlyDieselConsumption_L, dieselConsumptionPerWeek); + this.timestep_h = timeStep_h; + + this.activeConsumptionEnergyCarriers.add(OL_EnergyCarriers.DIESEL); + registerEnergyAsset(); + } + + @Override + public void f_updateAllFlows(double t_h) { + operate(t_h); + if (parentAgent instanceof GridConnection) { + ((GridConnection)parentAgent).f_addFlows(flowsMap, this.energyUse_kW, this); + } + this.lastFlowsMap.cloneMap(this.flowsMap); + this.lastEnergyUse_kW = this.energyUse_kW; + this.clear(); + } + + @Override + public void operate(double t_h) { + if (!shouldWork(t_h)) { + this.flowsMap.clear(); + return; + } + + double currentPower_kW = currentPower_kW(t_h); + + this.flowsMap.put(OL_EnergyCarriers.DIESEL, currentPower_kW); + this.energyUse_kW = currentPower_kW; + this.energyUsed_kWh += currentPower_kW * timestep_h; + } + + private static double[] calculateDieselConsumptionPerWeek_L(double yearlyDieselConsumption_l, double[] weekProfile) { + var profileSum = Arrays.stream(weekProfile).sum(); + + return Arrays.stream(weekProfile) + .map(weekValue -> yearlyDieselConsumption_l * weekValue / profileSum) + .toArray(); + } + + private boolean shouldWork(double currentStep_h) { + return isWorkTime(currentStep_h) && isWorkDay(); + } + + private boolean isWorkTime(double currentStep_h) { + double timeOfDay = currentStep_h % 24; + + return timeOfDay >= workDayStart_h && timeOfDay < workDayEnd_h; + } + + private boolean isWorkDay() { + return ((GridConnection)parentAgent).energyModel.b_isWeekday; + } + + private double workHoursPerWeek() { + return 5 * (workDayEnd_h - workDayStart_h); + } + + private int workTimeStepsPerWeek() { + return roundToInt(workHoursPerWeek() / this.timestep_h); + } + + private double currentPower_kW(double currentStep_h) { + int week = (int) Math.round(currentStep_h / (7 * 24)); + + double thisWeekDieselConsumption_L = this.dieselConsumptionPerWeek_L[week]; + double thisWeekDieselConsumption_kWh = thisWeekDieselConsumption_L * DIESEL_ENERGY_DENSITY_KWH_PER_L; + double power_kW = thisWeekDieselConsumption_kWh / workHoursPerWeek(); + return power_kW; + } + + /** + * This number is here for model snapshot storing purpose
+ * It needs to be changed when this class gets changed + */ + private static final long serialVersionUID = 1L; +}