diff --git a/.gitignore b/.gitignore
index 990f8eb..08cf438 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,5 +2,5 @@
/zero_engine
opencode.Containerfile
compose.yaml
-
+/site
.venv
diff --git a/README.md b/README.md
index 74d29c6..b976329 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,19 @@
+# LUX ENERGY TWIN DOCUMENTATION
-Source of [docs.lux.energy](https://docs.lux.energy)
+This repository contains the code for the user and the technical documentation for LUX Energy Twin, or LUX for short.
+
+For those just interested in reading the docs, they can be easily accessed at [docs.lux.energy](https://docs.lux.energy).
+
+The rest of this file is for those interested in contributing to the docs.
+
+The documentation guidelines can be found in the file: `documentation_guidelines`.
+
+The documentation is automatically deployed to the LUX website so that it is always up to date with the status of this repository.
+
+When developping the results can be viewed locally by running the following command:
+
+```
+podman run --volume .:/app docker.io/javanile/mkdocs:latest sh -c "pip3 install pymdown-extensions && mkdocs build"
+```
+
+This produces html files in the folder `site`, which can be opened in your browser of choice.
\ No newline at end of file
diff --git a/documentation_guidelines.md b/documentation_guidelines.md
new file mode 100644
index 0000000..28775b5
--- /dev/null
+++ b/documentation_guidelines.md
@@ -0,0 +1,40 @@
+# Documentation Guidelines
+
+This document is aimed to help you create documentation pages that match the structure and style of our docs. \
+The documentation is in markdown files \( \.md \), the basic syntax of which can be found [here](https://www.markdownguide.org/basic-syntax/)
+
+## What should be documented?
+
+Any sufficiently important Agent, Class or Function in the LUX model. The scope of the LUX model is: the engine, loader, interface, resultsUI and projectTemplate.
+
+Sufficiently important is ofcourse a subjective statement, but as a rule of thumb:
+
+> If a piece of code is of vital importance to the workings of the model, or contains assumptions that have significant impact on the model results it should be documented.
+
+## Structure of a documentation page
+
+All documentation pages should try to follow the same structure. The page should contain at least the following information:
+
+* A (short) introduction on the piece of code. How does it fit into the model's architecture. What function does it fulfil in the model.
+* If it is a class or agent, what are the most important parameters & variables? For each of those describe why it is of importance. You may also want to describe where the choice of parameter is determined or where it is used by the class.
+* If it is a class or agent, what are the most important functions & methods? For each of those describe why it is of importance.
+
+## Styling
+
+* Every page should start with a title, which is added by starting a line with a \# (Level 1 heading).
+* A page may contains paragraphs, which are added by lines starting with \#\# (Level 2 heading).
+* Small code snippits that fit inline and names of variables, classes, functions, etc. must be displayed between backticks \( \` \) \
+For example: `p_timeVariables.updateTimeVariables(v_timeStepsElapsed, p_timeParameters);`
+* Larger code snippits that span multiple lines must be displayed as fenced code blocks between three backticks \( \`\`\` \) \
+You can also specify the language of the code after the first three backticks, e.g. \`\`\`java \
+The result looks like this:
+```java
+for (GridConnection gc : c_gridConnections) {
+ gc.f_calculateEnergyBalance(p_timeVariables, v_isRapidRun);
+}
+```
+* Functions discriptions are code snippits, hence displayed between backticks. \
+Functions may list all their arguments, some of their arguments, or none of their arguments. \
+Arguments that are omitted are replaced with three dots \( \.\.\. \) \
+Usually from the arguments both the type and name is mentioned, the variable name is only mentioned in larger code snippits where it is relevant or when there is ambiguity , so not in function descriptions. \
+For example in `J_RapidRunData`: `addTimeStep( J_FlowsMap fm_currentBalanceFlows_kW, J_FlowsMap fm_currentConsumptionFlows_kW, ... , J_TimeVariables timeVariables)`
diff --git a/site/engine/consistency_checks/index.html b/site/engine/consistency_checks/index.html
index 68b7e0a..3f153f0 100644
--- a/site/engine/consistency_checks/index.html
+++ b/site/engine/consistency_checks/index.html
@@ -138,31 +138,31 @@
Consistency Checks
-
The LUX engine applies several consistency checks to ensure a correct and leak-free energy balance.
+
The LUX engine applies several consistency checks to ensure a correct model.
Configuration Check
The configuration check validates the model setup before simulation. It is implemented as f_checkConfiguration() methods on the EnergyModel and GridConnections .
The EnergyModel's f_checkConfiguration() iterates over all GridConnections and calls their individual check.
-
The GridConnection's f_checkConfiguration() checks:
+
The GridConnection's f_checkConfiguration() checks for:
-Flex assets without an EMS : If a GridConnection has flexible assets (c_flexAssets) but no I_EnergyManagement (EMS) is configured, a RuntimeException is thrown: "GC: {id} has flex assets, without an EMS".
-EMS-level validation : If an EMS is present, the check is delegated to the EMS's own checkConfiguration() method. Each EMS implementation validates that the set of flex assets matches its expected management types.
+Flex assets without an EMS : If a GridConnection has flexible assets (c_flexAssets) but no I_EnergyManagement (EMS) is configured, a RuntimeException is thrown.
+EMS-level validation : If an EMS is present, the check is delegated to the EMS's own checkConfiguration() method. Each EMS implementation validates that the set of flex assets matches its expected types.
-
This ensures that every agent with flexible equipment has a valid control system assigned before the simulation runs.
+
This ensures that every agent with flexible assets has a valid control system assigned before the simulation runs.
Energy Balance Check
The energy balance check (implemented as f_performEnergyBalanceCheck() on the EnergyModel) verifies the law of conservation of energy: energy cannot be created or destroyed in the model.
Energy can only enter or leave the model through these paths:
-Import of electricity, gas, hydrogen, and petroleum fuel.
-Export of electricity, gas, and hydrogen.
-Primary production : Energy harvested from the environment (e.g. wind, solar irradiation, ambient heat absorbed by buildings). Tracked as energyProduction_kW.
-Final consumption : Energy that leaves the system as losses (dissipated heat, conversion losses, consumption profiles). Tracked as energyConsumption_kW.
+Import of energy carriers.
+Export of energy carriers.
+Primary production : Energy harvested from the environment (e.g. wind, solar irradiation, ambient heat absorbed by buildings).
+Final consumption : Energy that leaves the system as losses (dissipated heat, conversion losses, consumption profiles).
The balance equation is:
-
Production - Export = Consumption - Import = SelfConsumption
+
Production - Export = Consumption - Import
In code, the check computes:
double energyBalanceCheck_MWh = totalImport_MWh + totalProduction_MWh
- (totalExport_MWh + totalConsumption_MWh + totalDeltaStoredEnergy_MWh);
-
This value must be zero. If it exceeds a tolerance of 1e-6 MWh, a warning is logged. The check also accounts for changes in stored energy (battery charge state, thermal storage in buildings) to prevent false positives from energy buffers that are not empty at the end of the simulation.
+
This value must be zero. If it exceeds a tolerance of 1e-6 MWh, a warning is logged. The check also accounts for changes in stored energy (battery charge state, thermal storage in buildings) to prevent false positives from energy buffers that the same at the end of the simulation compared to the start.
diff --git a/site/engine/data_structures/accumulator_maps/index.html b/site/engine/data_structures/accumulator_maps/index.html
index 9e6bafb..76718f6 100644
--- a/site/engine/data_structures/accumulator_maps/index.html
+++ b/site/engine/data_structures/accumulator_maps/index.html
@@ -135,7 +135,7 @@
Accumulator Maps
-
Accumulator Maps store a set of accumulators keyed by an enum type. The implementation is class J_AccumulatorMap<E extends Enum<E>>.
+
Accumulator Maps store a set of accumulators keyed by an enum type. The implementation is class J_AccumulatorMap<E extends Enum<E>>. During the simulation the results are stored in these accumulators. Agents loop over their energy carriers, asset flow categories or other option list and the individual accumulators are accessed and updated.
The constructor takes one argument:
Class\<E> enumClass : The enum type that defines the possible keys.
@@ -149,14 +149,8 @@ Accumulator Maps
reset() : Resets all accumulators in the map.
clear() : Removes all accumulators from the map.
keySet() : Returns the set of keys that have accumulators.
-
-
Just like the accumulator, it is possible to add or subtract entire accumulator maps (the keys must match).
-
Convenience methods for aggregating over all keys:
-
-totalIntegral_kWh() : Sum of getIntegral_kWh() across all accumulators.
-totalIntegralPos_kWh() : Sum of getIntegralPos_kWh() across all accumulators.
-totalIntegralNeg_kWh() : Sum of getIntegralNeg_kWh() across all accumulators.
-totalIntegral_MWh() / totalIntegralPos_MWh() / totalIntegralNeg_MWh() : MWh variants of the above.
+add(J_AccumulatorMap<E> accumulatorMap) : adds the accumulators of another accumulator map to the accumulators of this map and returns this object.
+subtract(J_AccumulatorMap<E> accumulatorMap) : subtracts the accumulators of another accumulator map to the accumulators of this map and returns this object.
Accumulator maps can be converted to DataSetMaps via getDataSetMap(startTime_h) or getDataSetMap(startTime_h, dataSetSignalResolution_h). The latter allows downsampling to a coarser signal resolution, given that it is a multiple of the accumulator's resolution.
diff --git a/site/engine/data_structures/dataset_maps/index.html b/site/engine/data_structures/dataset_maps/index.html
index df88fd3..64e6671 100644
--- a/site/engine/data_structures/dataset_maps/index.html
+++ b/site/engine/data_structures/dataset_maps/index.html
@@ -135,7 +135,7 @@
DataSet Maps
-
DataSet Maps store a set of AnyLogic DataSets (XY charts) keyed by an enum type. The implementation is class J_DataSetMap<E extends Enum<E>>.
+
DataSet Maps store a set of AnyLogic DataSets (2D XY data) keyed by an enum type. The implementation is class J_DataSetMap<E extends Enum<E>>.
DataSet Maps are typically created from accumulator maps via getDataSetMap(startTime_h), which converts each accumulator's time series to an AnyLogic DataSet for rendering charts and graphs.
The constructor accepts one argument:
diff --git a/site/engine/data_structures/profile_pointers/index.html b/site/engine/data_structures/profile_pointers/index.html
index c2a5337..cd0aa5e 100644
--- a/site/engine/data_structures/profile_pointers/index.html
+++ b/site/engine/data_structures/profile_pointers/index.html
@@ -139,7 +139,7 @@ Profile Pointers
Unlike Accumulators and Time Series which store simulation results , profile pointers read pre-defined input profiles. The profile data is stored as a double[] array with a fixed timestep.
The constructor accepts the following arguments:
-String name : A descriptive name for this profile (e.g. "temperature", "electricity_price").
+String name : A descriptive name for this profile (e.g. "ground_temperature", "day_ahead_electricity_price").
double[] profile : The array of data values.
double dataTimeStep_h : The time step between consecutive values in the profile array.
double dataStartTime_h : The start time of the first profile entry, relative to 00:00 on January 1st of the simulation year.
@@ -147,13 +147,13 @@ Profile Pointers
Key methods:
-getValue(double time_h) : Returns the profile value at the given simulation time. Supports profile looping: when enableProfileLooping is true (default), indices beyond the array length wrap around using modulo arithmetic.
-updateValue(double t_h) : Calls getValue(t_h) and stores the result internally.
getCurrentValue() : Returns the most recently updated value.
+getValue(double time_h) : Returns the profile value at the given simulation time. Supports profile looping: when enableProfileLooping is true (default), indices beyond the array length wrap around using modular arithmetic.
+updateValue(double t_h) : Calls getValue(t_h) and stores the result internally.
getAllValues() : Returns a clone of the full profile array.
getDataTimeStep_h() : Returns the time step of the profile data.
-The updateValue / getCurrentValue pattern is typically used each timestep during the simulation to avoid repeated index calculations.
+The updateValue / getCurrentValue pattern is used each timestep, called by the EnergyModel for all profile pointers during the simulation to avoid repeated index calculations.
For forecasting over a profile, see profile forecasters .
diff --git a/site/engine/energy_carriers/index.html b/site/engine/energy_carriers/index.html
index 7a427e3..e5a6dc0 100644
--- a/site/engine/energy_carriers/index.html
+++ b/site/engine/energy_carriers/index.html
@@ -145,7 +145,7 @@
Energy Carriers
Iron_powder
Other energycarriers can be easily added to the optionlist.
-All the datastructures, such as the accumulators in the rapidrundata, that store data for charts and graphs are dynamically extended to include these new energycarriers.
+All the datastructures, such as the accumulators in maps in the rapidrundata, that store data for charts and graphs are dynamically extended to include these new energycarriers.
The engine keeps track of which energycarriers are used in the model. This is done through the EnumSets activeProductionEnergyCarriers and activeConsumptionEnergyCarriers in the energy assets.
diff --git a/site/engine/energy_coops/index.html b/site/engine/energy_coops/index.html
index be87d04..31c56d0 100644
--- a/site/engine/energy_coops/index.html
+++ b/site/engine/energy_coops/index.html
@@ -142,14 +142,9 @@ Energy Cooperatives
The EnergyCoop agent implements I_EnergyData, exposing rapid-run and live data for results visualization. It extends the Actor class.
Key fields:
-c_memberGridConnections / c_customerGridConnections : GridConnections belonging to the cooperative as members (producers) or customers (consumers).
-v_energyPassedThrough_kWh : Total energy passed through the cooperative.
-v_electricityVolume_kWh / v_heatVolume_kWh / v_methaneVolume_kWh / v_hydrogenVolume_kWh : Energy volumes per carrier.
-
-Key methods:
-
-f_connectToChild(Actor, OL_EnergyCarriers) : Adds members and customers, categorizing them by actor group.
-f_updateIncentives() : Updates the cooperative's pricing incentives for its members.
+c_memberGridConnections / c_customerGridConnections : GridConnections belonging to the cooperative as members (producers) or customers (consumers). In an E-Hub all gridconnections are members.
+f_calculateEnergyBalance : This function is the main part of the engine loop every timestep. It resets the energy flows, loops through the coop members and customers to aggregate the energy flows. Then it stores the results in either the live data or rapidrun data class.
+f_operateAggregatorEnergyManagement : This function is called by the energymodel after all gridconnections have operated their assets and will determine the behaviour for the aggregated assets for the next timestep. This means aggregated assets in an EnergyCoop will always have one timestep delay in their behaviour.
The EnergyCoop agent allows for a centralized EMS that takes control from individual GridConnections and manages all (or a subset of) the flexible assets from a single point. This allows members of an Energy Hub to use more of their existing connection capacities or increase their combined self-consumption.
An example of an Energy Cooperative model developed with LUX is the Cooperatie Configurator . Models about Energy Hubs are usually restricted in their access because of the sensitive company data.
diff --git a/site/engine/energy_management_systems/index.html b/site/engine/energy_management_systems/index.html
index 615ae32..3f8ee81 100644
--- a/site/engine/energy_management_systems/index.html
+++ b/site/engine/energy_management_systems/index.html
@@ -61,10 +61,6 @@
@@ -145,29 +141,107 @@ Energy Management Systems
The Energy Management System (EMS) lives inside each GridConnection and decides what all the flexible assets do at every timestep. The interface is I_EnergyManagement.
There are three built-in implementations:
J_EnergyManagementDefault
-The default EMS that delegates to external sub-managers, called in the following order each timestep:
+The default EMS that delegates to external sub-managers, calls them in the following order each timestep:
Heating (I_HeatingManagement) — controls heat pumps and heating systems.
Charging (I_ChargingManagement) — manages EV charging sessions.
Battery (I_BatteryManagement) — operates stationary battery storage.
Backup Generator (I_BackupGeneratorManagement) — runs backup generators if needed.
-Curtailment (I_CurtailManagement) — curtails production when required.
+
+Curtailment (I_CurtailManagement) — curtails production when required.
+
+
+2f
+
+2f
+2f
+
+2f
+v
+
+
+werfvc
+
+werfvc
+werfvc
+
+werfvc
+v
+
+
+q3ewrf
+
+q3ewrf
+q3ewrf
+
+q3ewrf
+v
+
+
+43f
+
+43f
+43f
+
+43f
+v
+
+
+43f
+
+43f
+43f
+
+43f
+v
+
+
+43
+
+43
+43
+
+43
+v
+
+
+f43
+
+f43
+f43
+
+f43
+v
+
+
+f
+
+f
+f
+
+f
+v
+
+
+43f34
+
+43f34
+43f34
+
+43f34
+v
+
+
+
+
+v
-Constructor parameters: GridConnection GC, J_TimeParameters timeParameters.
-J_ISIE_EMS
-An integrated scheduling EMS that creates "virtual" assets for each flexible asset and schedules them using a merit order: EV → Heat Pump → Battery . It stores allowed operating times and min/max power for each asset, and creates a J_Market object per flex asset.
-Key features:
-* Self-consumption optimization : Maximizes on-site solar usage.
-* Peak shaving : Reduces peak import from the grid.
-* One-day-ahead scheduling : Makes a schedule based on a forecast.
-J_EnergyManagementElectrolyser
-Specialized EMS for electrolyser assets, managing hydrogen production and curtailment.
Custom EMS
You can implement your own EMS by implementing the I_EnergyManagement interface. The interface specifies:
manageFlexAssets(J_TimeVariables) : The main scheduling method called each timestep.
checkConfiguration(List<J_EAFlex>) : Validates that the set of flex assets is compatible with this EMS.
-getInternalAssetManagements() / getSupportedExternalAssetManagements() / getActiveExternalAssetManagements() : Provide and track sub-managers.
+getInternalAssetManagements() / getSupportedExternalAssetManagements() / getActiveExternalAssetManagements() : Provide and track the allowed sub-managers.
setExternalAssetManagement(...) / removeExternalAssetManagement(...) : Add or remove sub-managers dynamically.
Each EMS has a certain incentive — for example maximizing self-consumption from solar panels or reducing peak import from the grid. Systems can also differ in their approach: some decide at every timestep what to do in that same timestep, while others make a schedule based on a forecast.
diff --git a/site/engine/energy_model/index.html b/site/engine/energy_model/index.html
index 050d7ea..5a9fd49 100644
--- a/site/engine/energy_model/index.html
+++ b/site/engine/energy_model/index.html
@@ -141,20 +141,13 @@ Energy Model
c_gridConnections : All GridConnections in the simulation.
c_gridNodesTopLevel / c_gridNodesNotTopLevel / c_gridNodesHeat : The GridNode collections organized by hierarchy and energy carrier.
c_energyAssets / c_productionAssets / c_storageAssets / c_ambientDependentAssets : Asset collections for iteration and management.
-c_EVs : All electric vehicles in the model.
-The EnergyModel holds time parameters (J_TimeParameters) and profile pointers for weather and pricing data:
+The EnergyModel holds time parameters (J_TimeParameters) and time variables (J_TimeVariables) as well as profile pointers, like those for weather and pricing data:
pp_ambientTemperature_degC : Ambient temperature profile.
pp_windProduction_fr : Wind production factor profile.
pp_dayAheadElectricityPricing_eurpMWh : Day-ahead electricity price profile.
-Key methods:
-
-f_updatePricesForNextTimestep() : Updates energy prices, congestion tariffs, cooperative incentives, and propagates nodal pricing through the grid hierarchy at each timestep.
-f_updateTimeseries() : Advances all profile pointers and updates ambient-dependent assets.
-f_checkConfiguration() : Iterates over all GridConnections and validates consistency (see consistency checks ).
-
The engine runs two types of simulations: Live Simulation (interactive feedback) and RapidRun Simulation (batch comparison of scenarios).
diff --git a/site/engine/grid_connections/index.html b/site/engine/grid_connections/index.html
index 9092461..43f7963 100644
--- a/site/engine/grid_connections/index.html
+++ b/site/engine/grid_connections/index.html
@@ -135,7 +135,6 @@
GridConnections
GridConnections are agents that represent a connection to the grid. These are usually homes or companies, but could also be solar fields, windmills, charging stations, large-scale batteries, or district heating heat sources.
-The class implements I_EnergyData and I_AssetOwner.
Parameters:
p_gridConnectionID : A unique string to identify the GridConnection.
@@ -148,21 +147,6 @@ GridConnections
v_liveConnectionMetaData : Contains the contracted delivery/feed-in capacity, the physical capacity, and whether this information is known or estimated.
v_liveAssetsMetaData : Metadata about the assets (active flow categories, installed capacities).
-Flow Maps (updated every timestep):
-
-fm_currentProductionFlows_kW : Energy carrier production flows.
-fm_currentConsumptionFlows_kW : Energy carrier consumption flows.
-fm_currentBalanceFlows_kW : Net balance per energy carrier.
-fm_currentAssetFlows_kW : Flows per asset flow category .
-fm_consumptionForHeating_kW / fm_heatFromEnergyCarrier_kW : Heating-specific flows.
-
-Asset Collections:
-
-c_fixedAssets / c_flexAssets / c_profileAssets : Fixed, flexible, and profile-based assets.
-c_heatingAssets : Heat conversion assets.
-c_electricVehicles : EVs connected to this GridConnection.
-c_parentCoops : EnergyCoops that this GridConnection is a member of.
-
Key methods:
f_updateFlexAssetFlows() : Called by the EMS to operate the flexible energy assets.
diff --git a/site/engine/grid_nodes/index.html b/site/engine/grid_nodes/index.html
index 7a41084..bad483d 100644
--- a/site/engine/grid_nodes/index.html
+++ b/site/engine/grid_nodes/index.html
@@ -134,7 +134,7 @@
GridNodes
-
GridNodes are part of either the electricity or heat grid, depending on the value of p_energyCarrier. They form a hierarchical tree structure — the model does not support rings.
+
GridNodes are part of either the electricity or heat grid, depending on the value of p_energyCarrier. They form a hierarchical tree structure — the model does not support rings in the gridnode topology.
Parameters:
p_gridNodeID : A unique identifier (e.g. T0, T1, T2).
@@ -142,28 +142,12 @@ GridNodes
p_capacity_kW : The symmetrical capacity of this grid node.
p_realCapacityAvailable : Whether the capacity is known or estimated.
p_parentNodeID : The ID of the parent node in the tree.
-p_transportBuffer : A transport buffer parameter.
Collections:
c_connectedGridNodes : Child GridNodes connected below this node.
c_connectedGridConnections : GridConnections connected to this node.
c_energyCoops : EnergyCoops at this node.
-c_connectedConsumptionAssets / c_connectedProductionAssets / c_connectedStorageAssets / c_connectedConversionAssets : Aggregated asset collections.
-
-
State:
-
-v_congested : Whether this node is currently congested.
-v_congestionMode : The type of congestion (e.g. generation, consumption).
-v_peakLoadAbsolute_kW : The peak load measured at this node.
-v_loadFactor_fr : The load factor (utilization rate).
-
-
Key methods:
-
-f_connectToParentNode() : Connects this node to its parent GridNode and registers with the grid operator.
-f_connectToChild(Agent) : Adds a child GridNode, GridConnection, or EnergyCoop to the appropriate collection.
-f_propagateNodalPricing() : Propagates nodal pricing signals to child nodes and connections.
-f_getLowerLVLConnectedGridNodes() / f_getAllConnectedGridNodes_recursion() : Recursive topology traversal helpers.
diff --git a/site/index.html b/site/index.html
index 91b9dc2..2a62d41 100644
--- a/site/index.html
+++ b/site/index.html
@@ -213,5 +213,5 @@ What LUX can and cannot do
diff --git a/site/search/search_index.json b/site/search/search_index.json
index bb3613d..a13fc38 100644
--- a/site/search/search_index.json
+++ b/site/search/search_index.json
@@ -1 +1 @@
-{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Welcome to the LUX Model Documentation LUX Energy Twin (LUX for short) is an open-source, interactive, agent based model that simulates energy systems with a focus on electricity and the electricity grid. Example models to play around with can be found here on our website lux.energy LUX is built inside AnyLogic a multi-method simulation software platform that supports agent based modelling. A free version of this software called 'Personal Learning Edition' can be downloaded and is able to run the LUX models. LUX is written almost entirely in Java. The current AnyLogic version used is 8.9.7 and this uses Java 17. LUX makes use of many public datasets to make sure our models are always enriched with the best data. What LUX can and cannot do LUX does not simulate current and voltage, only power (kW) and power balance. Network lines (cables) are treated as a 'copper plate'. Substations and transformers have limited capacity. This means congestion can only occur at these nodes, not in cables. There is no infrastructure for energy carriers other than electricity. It is possible to simulate storages and buffers of other energy carriers, such as heat or hydrogen. Our models always have a live simulation that plays when the model first boots up and a rapid run simulation that can simulate headless. The live simulation shows the user direct feedback on his actions like changing scenario's or adding and removing assets. The rapidrun simulation is used to calculate and compare KPIs in a meaningful way. The model works in discrete timesteps. The default timestep of the simulation is 15 minute intervals. It is currently not recommend to change this parameter as it is not well tested at different settings. The duration of the simulation can be changed, but simulations longer than one year are currently not supported. 1 Every LUX model consists of 4 packages. Engine: Docs , Github Loader/Interface: Docs , Github ResultsUI: Docs , Github Project: Docs , Github The first three are public repositories that need not be altered for standard models. The fourth is a project specific package. These are not made public because of the sensitive data they contain. A template is made available that can be cloned and set up for your own projects. Simulations of at least two years are on the development roadmap as current Groepstransportoverenkomsten (GTO) calculations from grid operators are based on the previous two years. \u21a9","title":"Home"},{"location":"#welcome-to-the-lux-model-documentation","text":"LUX Energy Twin (LUX for short) is an open-source, interactive, agent based model that simulates energy systems with a focus on electricity and the electricity grid. Example models to play around with can be found here on our website lux.energy LUX is built inside AnyLogic a multi-method simulation software platform that supports agent based modelling. A free version of this software called 'Personal Learning Edition' can be downloaded and is able to run the LUX models. LUX is written almost entirely in Java. The current AnyLogic version used is 8.9.7 and this uses Java 17. LUX makes use of many public datasets to make sure our models are always enriched with the best data.","title":"Welcome to the LUX Model Documentation"},{"location":"#what-lux-can-and-cannot-do","text":"LUX does not simulate current and voltage, only power (kW) and power balance. Network lines (cables) are treated as a 'copper plate'. Substations and transformers have limited capacity. This means congestion can only occur at these nodes, not in cables. There is no infrastructure for energy carriers other than electricity. It is possible to simulate storages and buffers of other energy carriers, such as heat or hydrogen. Our models always have a live simulation that plays when the model first boots up and a rapid run simulation that can simulate headless. The live simulation shows the user direct feedback on his actions like changing scenario's or adding and removing assets. The rapidrun simulation is used to calculate and compare KPIs in a meaningful way. The model works in discrete timesteps. The default timestep of the simulation is 15 minute intervals. It is currently not recommend to change this parameter as it is not well tested at different settings. The duration of the simulation can be changed, but simulations longer than one year are currently not supported. 1 Every LUX model consists of 4 packages. Engine: Docs , Github Loader/Interface: Docs , Github ResultsUI: Docs , Github Project: Docs , Github The first three are public repositories that need not be altered for standard models. The fourth is a project specific package. These are not made public because of the sensitive data they contain. A template is made available that can be cloned and set up for your own projects. Simulations of at least two years are on the development roadmap as current Groepstransportoverenkomsten (GTO) calculations from grid operators are based on the previous two years. \u21a9","title":"What LUX can and cannot do"},{"location":"engine/consistency_checks/","text":"Consistency Checks The LUX engine applies several consistency checks to ensure a correct and leak-free energy balance. Configuration Check The configuration check validates the model setup before simulation. It is implemented as f_checkConfiguration() methods on the EnergyModel and GridConnections . The EnergyModel's f_checkConfiguration() iterates over all GridConnections and calls their individual check. The GridConnection's f_checkConfiguration() checks: Flex assets without an EMS : If a GridConnection has flexible assets ( c_flexAssets ) but no I_EnergyManagement (EMS) is configured, a RuntimeException is thrown: \"GC: {id} has flex assets, without an EMS\" . EMS-level validation : If an EMS is present, the check is delegated to the EMS's own checkConfiguration() method. Each EMS implementation validates that the set of flex assets matches its expected management types. This ensures that every agent with flexible equipment has a valid control system assigned before the simulation runs. Energy Balance Check The energy balance check (implemented as f_performEnergyBalanceCheck() on the EnergyModel) verifies the law of conservation of energy: energy cannot be created or destroyed in the model. Energy can only enter or leave the model through these paths: Import of electricity, gas, hydrogen, and petroleum fuel. Export of electricity, gas, and hydrogen. Primary production : Energy harvested from the environment (e.g. wind, solar irradiation, ambient heat absorbed by buildings). Tracked as energyProduction_kW . Final consumption : Energy that leaves the system as losses (dissipated heat, conversion losses, consumption profiles). Tracked as energyConsumption_kW . The balance equation is: Production - Export = Consumption - Import = SelfConsumption In code, the check computes: double energyBalanceCheck_MWh = totalImport_MWh + totalProduction_MWh - (totalExport_MWh + totalConsumption_MWh + totalDeltaStoredEnergy_MWh); This value must be zero. If it exceeds a tolerance of 1e-6 MWh, a warning is logged. The check also accounts for changes in stored energy (battery charge state, thermal storage in buildings) to prevent false positives from energy buffers that are not empty at the end of the simulation.","title":"Consistency Checks"},{"location":"engine/consistency_checks/#consistency-checks","text":"The LUX engine applies several consistency checks to ensure a correct and leak-free energy balance.","title":"Consistency Checks"},{"location":"engine/consistency_checks/#configuration-check","text":"The configuration check validates the model setup before simulation. It is implemented as f_checkConfiguration() methods on the EnergyModel and GridConnections . The EnergyModel's f_checkConfiguration() iterates over all GridConnections and calls their individual check. The GridConnection's f_checkConfiguration() checks: Flex assets without an EMS : If a GridConnection has flexible assets ( c_flexAssets ) but no I_EnergyManagement (EMS) is configured, a RuntimeException is thrown: \"GC: {id} has flex assets, without an EMS\" . EMS-level validation : If an EMS is present, the check is delegated to the EMS's own checkConfiguration() method. Each EMS implementation validates that the set of flex assets matches its expected management types. This ensures that every agent with flexible equipment has a valid control system assigned before the simulation runs.","title":"Configuration Check"},{"location":"engine/consistency_checks/#energy-balance-check","text":"The energy balance check (implemented as f_performEnergyBalanceCheck() on the EnergyModel) verifies the law of conservation of energy: energy cannot be created or destroyed in the model. Energy can only enter or leave the model through these paths: Import of electricity, gas, hydrogen, and petroleum fuel. Export of electricity, gas, and hydrogen. Primary production : Energy harvested from the environment (e.g. wind, solar irradiation, ambient heat absorbed by buildings). Tracked as energyProduction_kW . Final consumption : Energy that leaves the system as losses (dissipated heat, conversion losses, consumption profiles). Tracked as energyConsumption_kW . The balance equation is: Production - Export = Consumption - Import = SelfConsumption In code, the check computes: double energyBalanceCheck_MWh = totalImport_MWh + totalProduction_MWh - (totalExport_MWh + totalConsumption_MWh + totalDeltaStoredEnergy_MWh); This value must be zero. If it exceeds a tolerance of 1e-6 MWh, a warning is logged. The check also accounts for changes in stored energy (battery charge state, thermal storage in buildings) to prevent false positives from energy buffers that are not empty at the end of the simulation.","title":"Energy Balance Check"},{"location":"engine/energy_assets/","text":"Energy Assets EnergyAssets are a core class in the LUX model. Everything that produces, consumes or converts energy in the model is an energy asset. The energy assets in the model have a hierarchical structure. At the top of the tree is the distinction between J_EAFixed and J_EAFlex. Fixed assets are assets that have predetermined behaviour. These are 'profiles' that are played during the simulation. An example for a fixed asset is the baseload consumption of a household or the production of a solar panel. There can be flexibility in these assets, for example by curtailing the solar power, but a priori there is none. Flex assets are assets that require, at every timestep, to be told at what power they are operated. This decision is made by an EMS The full tree of the hierarchical structure of energy assets can be seen in image X. Energy assets have two important option lists : energyAssetType: This determines the category of the energy asset. This optionlist can seem redundant 1 because of the different classes, but allows us to use data such as profiles of EV charging sessions and keep the bookkeeping consistent with simulated J_EAEVs. assetFlowCategory: This determines under which category the energy flows of this asset fall in the graphs and charts When energyassets are created they register themselves at their GridConnection through the method registerEnergyAsset(). At every timestep the assets are operated through the method f_updateAllFlows(). At the start of a rapidrun the current state of the asset in the live simulation is stored with the method storeStatesAndReset(), at the end of the headless run the states are restored through restoreStates(). Energy assets also keep track of a variable called 'EnergyUsed_kWh', this variable contains all the energy losses of the asset. At the end of a rapidrun simulation these losses are compared to the bookkeeping of the gridconnection and energymodel to make sure no energy has disappeared or is created out of thin air. See also Consistency Checks We are actually trying to remove the optionlist OL_EnergyAssetType, because it has exploded too much in size and are currently looking into ways to split this into multiple smaller option lists like OL_ProductionType, OL_VehicleType, etc. \u21a9","title":"Energy Assets"},{"location":"engine/energy_assets/#energy-assets","text":"EnergyAssets are a core class in the LUX model. Everything that produces, consumes or converts energy in the model is an energy asset. The energy assets in the model have a hierarchical structure. At the top of the tree is the distinction between J_EAFixed and J_EAFlex. Fixed assets are assets that have predetermined behaviour. These are 'profiles' that are played during the simulation. An example for a fixed asset is the baseload consumption of a household or the production of a solar panel. There can be flexibility in these assets, for example by curtailing the solar power, but a priori there is none. Flex assets are assets that require, at every timestep, to be told at what power they are operated. This decision is made by an EMS The full tree of the hierarchical structure of energy assets can be seen in image X. Energy assets have two important option lists : energyAssetType: This determines the category of the energy asset. This optionlist can seem redundant 1 because of the different classes, but allows us to use data such as profiles of EV charging sessions and keep the bookkeeping consistent with simulated J_EAEVs. assetFlowCategory: This determines under which category the energy flows of this asset fall in the graphs and charts When energyassets are created they register themselves at their GridConnection through the method registerEnergyAsset(). At every timestep the assets are operated through the method f_updateAllFlows(). At the start of a rapidrun the current state of the asset in the live simulation is stored with the method storeStatesAndReset(), at the end of the headless run the states are restored through restoreStates(). Energy assets also keep track of a variable called 'EnergyUsed_kWh', this variable contains all the energy losses of the asset. At the end of a rapidrun simulation these losses are compared to the bookkeeping of the gridconnection and energymodel to make sure no energy has disappeared or is created out of thin air. See also Consistency Checks We are actually trying to remove the optionlist OL_EnergyAssetType, because it has exploded too much in size and are currently looking into ways to split this into multiple smaller option lists like OL_ProductionType, OL_VehicleType, etc. \u21a9","title":"Energy Assets"},{"location":"engine/energy_carriers/","text":"Energy Carriers The energycarriers in LUX are found in the optionlist OL_EnergyCarriers in the engine. By default this optionlist contains the following energycarriers: Electricity Heat Methane Petroleum_fuel Hydrogen Iron_powder Other energycarriers can be easily added to the optionlist. All the datastructures, such as the accumulators in the rapidrundata, that store data for charts and graphs are dynamically extended to include these new energycarriers. The engine keeps track of which energycarriers are used in the model. This is done through the EnumSets activeProductionEnergyCarriers and activeConsumptionEnergyCarriers in the energy assets.","title":"Energy Carriers"},{"location":"engine/energy_carriers/#energy-carriers","text":"The energycarriers in LUX are found in the optionlist OL_EnergyCarriers in the engine. By default this optionlist contains the following energycarriers: Electricity Heat Methane Petroleum_fuel Hydrogen Iron_powder Other energycarriers can be easily added to the optionlist. All the datastructures, such as the accumulators in the rapidrundata, that store data for charts and graphs are dynamically extended to include these new energycarriers. The engine keeps track of which energycarriers are used in the model. This is done through the EnumSets activeProductionEnergyCarriers and activeConsumptionEnergyCarriers in the energy assets.","title":"Energy Carriers"},{"location":"engine/energy_coops/","text":"Energy Cooperatives Energy cooperatives (or EnergyCoops for short) have two separate use cases in the engine. The traditional meaning: a community-owned cooperative that offers a sustainable, community-focused alternative to traditional energy providers. As a collection of GridConnections , usually businesses, that form an Energy Hub to share energy and/or contracted capacity. The EnergyCoop agent implements I_EnergyData , exposing rapid-run and live data for results visualization. It extends the Actor class. Key fields: c_memberGridConnections / c_customerGridConnections : GridConnections belonging to the cooperative as members (producers) or customers (consumers). v_energyPassedThrough_kWh : Total energy passed through the cooperative. v_electricityVolume_kWh / v_heatVolume_kWh / v_methaneVolume_kWh / v_hydrogenVolume_kWh : Energy volumes per carrier. Key methods: f_connectToChild(Actor, OL_EnergyCarriers) : Adds members and customers, categorizing them by actor group. f_updateIncentives() : Updates the cooperative's pricing incentives for its members. The EnergyCoop agent allows for a centralized EMS that takes control from individual GridConnections and manages all (or a subset of) the flexible assets from a single point. This allows members of an Energy Hub to use more of their existing connection capacities or increase their combined self-consumption. An example of an Energy Cooperative model developed with LUX is the Cooperatie Configurator . Models about Energy Hubs are usually restricted in their access because of the sensitive company data.","title":"Energy Cooperatives"},{"location":"engine/energy_coops/#energy-cooperatives","text":"Energy cooperatives (or EnergyCoops for short) have two separate use cases in the engine. The traditional meaning: a community-owned cooperative that offers a sustainable, community-focused alternative to traditional energy providers. As a collection of GridConnections , usually businesses, that form an Energy Hub to share energy and/or contracted capacity. The EnergyCoop agent implements I_EnergyData , exposing rapid-run and live data for results visualization. It extends the Actor class. Key fields: c_memberGridConnections / c_customerGridConnections : GridConnections belonging to the cooperative as members (producers) or customers (consumers). v_energyPassedThrough_kWh : Total energy passed through the cooperative. v_electricityVolume_kWh / v_heatVolume_kWh / v_methaneVolume_kWh / v_hydrogenVolume_kWh : Energy volumes per carrier. Key methods: f_connectToChild(Actor, OL_EnergyCarriers) : Adds members and customers, categorizing them by actor group. f_updateIncentives() : Updates the cooperative's pricing incentives for its members. The EnergyCoop agent allows for a centralized EMS that takes control from individual GridConnections and manages all (or a subset of) the flexible assets from a single point. This allows members of an Energy Hub to use more of their existing connection capacities or increase their combined self-consumption. An example of an Energy Cooperative model developed with LUX is the Cooperatie Configurator . Models about Energy Hubs are usually restricted in their access because of the sensitive company data.","title":"Energy Cooperatives"},{"location":"engine/energy_data/","text":"EnergyData I_EnergyData is an interface implemented by three agents: GridConnections EnergyCoops EnergyModel The interface specifies 4 methods: * getLiveData() * getRapidRunData() * getPreviousRapidRunData() * getScope() This allows the resultsUI to request data for charts and graphs from different agents in the engine in a standerdized method. The data stored in GridNodes and their available charts differ too much to be included in this list. The agent EnergyDataViewer is used when debugging to inspect the data in the live and rapidrun classes. A button labeled 'View Data' is available on the canvasses of the three agents to take fill the data viewer and navigate to it.","title":"Energy Data"},{"location":"engine/energy_data/#energydata","text":"I_EnergyData is an interface implemented by three agents: GridConnections EnergyCoops EnergyModel The interface specifies 4 methods: * getLiveData() * getRapidRunData() * getPreviousRapidRunData() * getScope() This allows the resultsUI to request data for charts and graphs from different agents in the engine in a standerdized method. The data stored in GridNodes and their available charts differ too much to be included in this list. The agent EnergyDataViewer is used when debugging to inspect the data in the live and rapidrun classes. A button labeled 'View Data' is available on the canvasses of the three agents to take fill the data viewer and navigate to it.","title":"EnergyData"},{"location":"engine/energy_management_systems/","text":"Energy Management Systems The Energy Management System (EMS) lives inside each GridConnection and decides what all the flexible assets do at every timestep. The interface is I_EnergyManagement . There are three built-in implementations: J_EnergyManagementDefault The default EMS that delegates to external sub-managers, called in the following order each timestep: Heating ( I_HeatingManagement ) \u2014 controls heat pumps and heating systems. Charging ( I_ChargingManagement ) \u2014 manages EV charging sessions. Battery ( I_BatteryManagement ) \u2014 operates stationary battery storage. Backup Generator ( I_BackupGeneratorManagement ) \u2014 runs backup generators if needed. Curtailment ( I_CurtailManagement ) \u2014 curtails production when required. Constructor parameters: GridConnection GC , J_TimeParameters timeParameters . J_ISIE_EMS An integrated scheduling EMS that creates \"virtual\" assets for each flexible asset and schedules them using a merit order: EV \u2192 Heat Pump \u2192 Battery . It stores allowed operating times and min/max power for each asset, and creates a J_Market object per flex asset. Key features: * Self-consumption optimization : Maximizes on-site solar usage. * Peak shaving : Reduces peak import from the grid. * One-day-ahead scheduling : Makes a schedule based on a forecast. J_EnergyManagementElectrolyser Specialized EMS for electrolyser assets, managing hydrogen production and curtailment. Custom EMS You can implement your own EMS by implementing the I_EnergyManagement interface. The interface specifies: manageFlexAssets(J_TimeVariables) : The main scheduling method called each timestep. checkConfiguration(List) : Validates that the set of flex assets is compatible with this EMS. getInternalAssetManagements() / getSupportedExternalAssetManagements() / getActiveExternalAssetManagements() : Provide and track sub-managers. setExternalAssetManagement(...) / removeExternalAssetManagement(...) : Add or remove sub-managers dynamically. Each EMS has a certain incentive \u2014 for example maximizing self-consumption from solar panels or reducing peak import from the grid. Systems can also differ in their approach: some decide at every timestep what to do in that same timestep, while others make a schedule based on a forecast.","title":"Energy Management Systems"},{"location":"engine/energy_management_systems/#energy-management-systems","text":"The Energy Management System (EMS) lives inside each GridConnection and decides what all the flexible assets do at every timestep. The interface is I_EnergyManagement . There are three built-in implementations:","title":"Energy Management Systems"},{"location":"engine/energy_management_systems/#j_energymanagementdefault","text":"The default EMS that delegates to external sub-managers, called in the following order each timestep: Heating ( I_HeatingManagement ) \u2014 controls heat pumps and heating systems. Charging ( I_ChargingManagement ) \u2014 manages EV charging sessions. Battery ( I_BatteryManagement ) \u2014 operates stationary battery storage. Backup Generator ( I_BackupGeneratorManagement ) \u2014 runs backup generators if needed. Curtailment ( I_CurtailManagement ) \u2014 curtails production when required. Constructor parameters: GridConnection GC , J_TimeParameters timeParameters .","title":"J_EnergyManagementDefault"},{"location":"engine/energy_management_systems/#j_isie_ems","text":"An integrated scheduling EMS that creates \"virtual\" assets for each flexible asset and schedules them using a merit order: EV \u2192 Heat Pump \u2192 Battery . It stores allowed operating times and min/max power for each asset, and creates a J_Market object per flex asset. Key features: * Self-consumption optimization : Maximizes on-site solar usage. * Peak shaving : Reduces peak import from the grid. * One-day-ahead scheduling : Makes a schedule based on a forecast.","title":"J_ISIE_EMS"},{"location":"engine/energy_management_systems/#j_energymanagementelectrolyser","text":"Specialized EMS for electrolyser assets, managing hydrogen production and curtailment.","title":"J_EnergyManagementElectrolyser"},{"location":"engine/energy_management_systems/#custom-ems","text":"You can implement your own EMS by implementing the I_EnergyManagement interface. The interface specifies: manageFlexAssets(J_TimeVariables) : The main scheduling method called each timestep. checkConfiguration(List) : Validates that the set of flex assets is compatible with this EMS. getInternalAssetManagements() / getSupportedExternalAssetManagements() / getActiveExternalAssetManagements() : Provide and track sub-managers. setExternalAssetManagement(...) / removeExternalAssetManagement(...) : Add or remove sub-managers dynamically. Each EMS has a certain incentive \u2014 for example maximizing self-consumption from solar panels or reducing peak import from the grid. Systems can also differ in their approach: some decide at every timestep what to do in that same timestep, while others make a schedule based on a forecast.","title":"Custom EMS"},{"location":"engine/energy_model/","text":"Energy Model The EnergyModel is the top-level simulation agent of the engine . It orchestrates the entire simulation by managing all other agent populations \u2014 GridConnections , GridNodes , and EnergyCoops \u2014 and stepping through time. The EnergyModel is also where all energy flows of all agents in the model accumulate at each timestep. The following key collections are held by the EnergyModel: c_gridConnections : All GridConnections in the simulation. c_gridNodesTopLevel / c_gridNodesNotTopLevel / c_gridNodesHeat : The GridNode collections organized by hierarchy and energy carrier. c_energyAssets / c_productionAssets / c_storageAssets / c_ambientDependentAssets : Asset collections for iteration and management. c_EVs : All electric vehicles in the model. The EnergyModel holds time parameters ( J_TimeParameters ) and profile pointers for weather and pricing data: pp_ambientTemperature_degC : Ambient temperature profile. pp_windProduction_fr : Wind production factor profile. pp_dayAheadElectricityPricing_eurpMWh : Day-ahead electricity price profile. Key methods: f_updatePricesForNextTimestep() : Updates energy prices, congestion tariffs, cooperative incentives, and propagates nodal pricing through the grid hierarchy at each timestep. f_updateTimeseries() : Advances all profile pointers and updates ambient-dependent assets. f_checkConfiguration() : Iterates over all GridConnections and validates consistency (see consistency checks ). The engine runs two types of simulations: Live Simulation (interactive feedback) and RapidRun Simulation (batch comparison of scenarios).","title":"Energy Model"},{"location":"engine/energy_model/#energy-model","text":"The EnergyModel is the top-level simulation agent of the engine . It orchestrates the entire simulation by managing all other agent populations \u2014 GridConnections , GridNodes , and EnergyCoops \u2014 and stepping through time. The EnergyModel is also where all energy flows of all agents in the model accumulate at each timestep. The following key collections are held by the EnergyModel: c_gridConnections : All GridConnections in the simulation. c_gridNodesTopLevel / c_gridNodesNotTopLevel / c_gridNodesHeat : The GridNode collections organized by hierarchy and energy carrier. c_energyAssets / c_productionAssets / c_storageAssets / c_ambientDependentAssets : Asset collections for iteration and management. c_EVs : All electric vehicles in the model. The EnergyModel holds time parameters ( J_TimeParameters ) and profile pointers for weather and pricing data: pp_ambientTemperature_degC : Ambient temperature profile. pp_windProduction_fr : Wind production factor profile. pp_dayAheadElectricityPricing_eurpMWh : Day-ahead electricity price profile. Key methods: f_updatePricesForNextTimestep() : Updates energy prices, congestion tariffs, cooperative incentives, and propagates nodal pricing through the grid hierarchy at each timestep. f_updateTimeseries() : Advances all profile pointers and updates ambient-dependent assets. f_checkConfiguration() : Iterates over all GridConnections and validates consistency (see consistency checks ). The engine runs two types of simulations: Live Simulation (interactive feedback) and RapidRun Simulation (batch comparison of scenarios).","title":"Energy Model"},{"location":"engine/grid_connections/","text":"GridConnections GridConnections are agents that represent a connection to the grid. These are usually homes or companies, but could also be solar fields, windmills, charging stations, large-scale batteries, or district heating heat sources. The class implements I_EnergyData and I_AssetOwner . Parameters: p_gridConnectionID : A unique string to identify the GridConnection. p_address : A class containing address details (postal code, street name, house number, etc.). p_energyManagement : The EMS ( I_EnergyManagement ) controlling the flexible assets. p_parentNodeElectricID / p_parentNodeHeatID : The IDs of the parent GridNodes for electricity and heat. Metadata: v_liveConnectionMetaData : Contains the contracted delivery/feed-in capacity, the physical capacity, and whether this information is known or estimated. v_liveAssetsMetaData : Metadata about the assets (active flow categories, installed capacities). Flow Maps (updated every timestep): fm_currentProductionFlows_kW : Energy carrier production flows. fm_currentConsumptionFlows_kW : Energy carrier consumption flows. fm_currentBalanceFlows_kW : Net balance per energy carrier. fm_currentAssetFlows_kW : Flows per asset flow category . fm_consumptionForHeating_kW / fm_heatFromEnergyCarrier_kW : Heating-specific flows. Asset Collections: c_fixedAssets / c_flexAssets / c_profileAssets : Fixed, flexible, and profile-based assets. c_heatingAssets : Heat conversion assets. c_electricVehicles : EVs connected to this GridConnection. c_parentCoops : EnergyCoops that this GridConnection is a member of. Key methods: f_updateFlexAssetFlows() : Called by the EMS to operate the flexible energy assets. f_connectToJ_EA(J_EAFixed) / f_removeTheJ_EAFixed(J_EAFixed) : Add and remove energy assets. f_calculateEnergyBalance() : Part of the main simulation loop. Called by the EnergyModel at every timestep. Resets all per-timestep values, then manages and operates all assets. f_connectionMetering() : Called at the end of f_calculateEnergyBalance . Checks for heat imbalances (which would stop the simulation), then stores the timestep data in the live or rapid-run data classes.","title":"Grid Connections"},{"location":"engine/grid_connections/#gridconnections","text":"GridConnections are agents that represent a connection to the grid. These are usually homes or companies, but could also be solar fields, windmills, charging stations, large-scale batteries, or district heating heat sources. The class implements I_EnergyData and I_AssetOwner . Parameters: p_gridConnectionID : A unique string to identify the GridConnection. p_address : A class containing address details (postal code, street name, house number, etc.). p_energyManagement : The EMS ( I_EnergyManagement ) controlling the flexible assets. p_parentNodeElectricID / p_parentNodeHeatID : The IDs of the parent GridNodes for electricity and heat. Metadata: v_liveConnectionMetaData : Contains the contracted delivery/feed-in capacity, the physical capacity, and whether this information is known or estimated. v_liveAssetsMetaData : Metadata about the assets (active flow categories, installed capacities). Flow Maps (updated every timestep): fm_currentProductionFlows_kW : Energy carrier production flows. fm_currentConsumptionFlows_kW : Energy carrier consumption flows. fm_currentBalanceFlows_kW : Net balance per energy carrier. fm_currentAssetFlows_kW : Flows per asset flow category . fm_consumptionForHeating_kW / fm_heatFromEnergyCarrier_kW : Heating-specific flows. Asset Collections: c_fixedAssets / c_flexAssets / c_profileAssets : Fixed, flexible, and profile-based assets. c_heatingAssets : Heat conversion assets. c_electricVehicles : EVs connected to this GridConnection. c_parentCoops : EnergyCoops that this GridConnection is a member of. Key methods: f_updateFlexAssetFlows() : Called by the EMS to operate the flexible energy assets. f_connectToJ_EA(J_EAFixed) / f_removeTheJ_EAFixed(J_EAFixed) : Add and remove energy assets. f_calculateEnergyBalance() : Part of the main simulation loop. Called by the EnergyModel at every timestep. Resets all per-timestep values, then manages and operates all assets. f_connectionMetering() : Called at the end of f_calculateEnergyBalance . Checks for heat imbalances (which would stop the simulation), then stores the timestep data in the live or rapid-run data classes.","title":"GridConnections"},{"location":"engine/grid_nodes/","text":"GridNodes GridNodes are part of either the electricity or heat grid, depending on the value of p_energyCarrier . They form a hierarchical tree structure \u2014 the model does not support rings. Parameters: p_gridNodeID : A unique identifier (e.g. T0, T1, T2). p_energyCarrier : The OL_EnergyCarriers type for this node (electricity or heat). p_capacity_kW : The symmetrical capacity of this grid node. p_realCapacityAvailable : Whether the capacity is known or estimated. p_parentNodeID : The ID of the parent node in the tree. p_transportBuffer : A transport buffer parameter. Collections: c_connectedGridNodes : Child GridNodes connected below this node. c_connectedGridConnections : GridConnections connected to this node. c_energyCoops : EnergyCoops at this node. c_connectedConsumptionAssets / c_connectedProductionAssets / c_connectedStorageAssets / c_connectedConversionAssets : Aggregated asset collections. State: v_congested : Whether this node is currently congested. v_congestionMode : The type of congestion (e.g. generation, consumption). v_peakLoadAbsolute_kW : The peak load measured at this node. v_loadFactor_fr : The load factor (utilization rate). Key methods: f_connectToParentNode() : Connects this node to its parent GridNode and registers with the grid operator. f_connectToChild(Agent) : Adds a child GridNode, GridConnection, or EnergyCoop to the appropriate collection. f_propagateNodalPricing() : Propagates nodal pricing signals to child nodes and connections. f_getLowerLVLConnectedGridNodes() / f_getAllConnectedGridNodes_recursion() : Recursive topology traversal helpers.","title":"Grid Nodes"},{"location":"engine/grid_nodes/#gridnodes","text":"GridNodes are part of either the electricity or heat grid, depending on the value of p_energyCarrier . They form a hierarchical tree structure \u2014 the model does not support rings. Parameters: p_gridNodeID : A unique identifier (e.g. T0, T1, T2). p_energyCarrier : The OL_EnergyCarriers type for this node (electricity or heat). p_capacity_kW : The symmetrical capacity of this grid node. p_realCapacityAvailable : Whether the capacity is known or estimated. p_parentNodeID : The ID of the parent node in the tree. p_transportBuffer : A transport buffer parameter. Collections: c_connectedGridNodes : Child GridNodes connected below this node. c_connectedGridConnections : GridConnections connected to this node. c_energyCoops : EnergyCoops at this node. c_connectedConsumptionAssets / c_connectedProductionAssets / c_connectedStorageAssets / c_connectedConversionAssets : Aggregated asset collections. State: v_congested : Whether this node is currently congested. v_congestionMode : The type of congestion (e.g. generation, consumption). v_peakLoadAbsolute_kW : The peak load measured at this node. v_loadFactor_fr : The load factor (utilization rate). Key methods: f_connectToParentNode() : Connects this node to its parent GridNode and registers with the grid operator. f_connectToChild(Agent) : Adds a child GridNode, GridConnection, or EnergyCoop to the appropriate collection. f_propagateNodalPricing() : Propagates nodal pricing signals to child nodes and connections. f_getLowerLVLConnectedGridNodes() / f_getAllConnectedGridNodes_recursion() : Recursive topology traversal helpers.","title":"GridNodes"},{"location":"engine/option_lists/","text":"OptionLists, abbreviated as OL, are AnyLogics version of Java Enums. There are many OptionLists in the LUX model. Some of the more commonly used are: OL_EnergyCarriers OL_AssetFlowCategories OL_EnergyAssetType OL_GridConnectionHeatingType OL_GridNodeType Option lists always have the prefix 'OL'. Entries in option lists are always capitalized, with underscores for spaces. e.g. ELECTRICITY, PETROLEUM_FUEL.","title":"Option Lists"},{"location":"engine/overview/","text":"Engine The engine is the main component of the simulation software. The engine contains the needed classes to input a full description of the energy system, as well as the tools to run simulations. This includes the decision making algorithms that decide the behaviour of agents as well as the data structures to store all the results of a simulation. The main agent of the engine is called the EnergyModel . This agent contains all other agent populations, like all the GridConnections and GridNodes . The EnergyModel is also where all the energy flows of all agents living in the model accumulate. The populations of agents in the engine are filled by the loader . The engine runs two types of simulations: * Live Simulation * RapidRun Simulation The live simulation serves to give direct feedback to user inputs in the interface . The rapidrun simulation is used to compare model results and KPIs between different scenarios.","title":"Overview"},{"location":"engine/overview/#engine","text":"The engine is the main component of the simulation software. The engine contains the needed classes to input a full description of the energy system, as well as the tools to run simulations. This includes the decision making algorithms that decide the behaviour of agents as well as the data structures to store all the results of a simulation. The main agent of the engine is called the EnergyModel . This agent contains all other agent populations, like all the GridConnections and GridNodes . The EnergyModel is also where all the energy flows of all agents living in the model accumulate. The populations of agents in the engine are filled by the loader . The engine runs two types of simulations: * Live Simulation * RapidRun Simulation The live simulation serves to give direct feedback to user inputs in the interface . The rapidrun simulation is used to compare model results and KPIs between different scenarios.","title":"Engine"},{"location":"engine/data_structures/accumulator_maps/","text":"Accumulator Maps Accumulator Maps store a set of accumulators keyed by an enum type. The implementation is class J_AccumulatorMap> . The constructor takes one argument: Class\\ enumClass : The enum type that defines the possible keys. Key methods: createEmptyAccumulators(EnumSet selectedFlows, boolean hasTimeSeries, double signalResolution_h, double duration_h) : Fills the map with accumulators for the given subset of enum keys. All accumulators are created with the same parameters. put(E key, ZeroAccumulator acc) : Adds an individual accumulator for a specific key. get(E key) : Retrieves the accumulator for a given key. getClone() : Returns a deep clone of this map, cloning each accumulator. reset() : Resets all accumulators in the map. clear() : Removes all accumulators from the map. keySet() : Returns the set of keys that have accumulators. Just like the accumulator, it is possible to add or subtract entire accumulator maps (the keys must match). Convenience methods for aggregating over all keys: totalIntegral_kWh() : Sum of getIntegral_kWh() across all accumulators. totalIntegralPos_kWh() : Sum of getIntegralPos_kWh() across all accumulators. totalIntegralNeg_kWh() : Sum of getIntegralNeg_kWh() across all accumulators. totalIntegral_MWh() / totalIntegralPos_MWh() / totalIntegralNeg_MWh() : MWh variants of the above. Accumulator maps can be converted to DataSetMaps via getDataSetMap(startTime_h) or getDataSetMap(startTime_h, dataSetSignalResolution_h) . The latter allows downsampling to a coarser signal resolution, given that it is a multiple of the accumulator's resolution.","title":"Accumulator Maps"},{"location":"engine/data_structures/accumulator_maps/#accumulator-maps","text":"Accumulator Maps store a set of accumulators keyed by an enum type. The implementation is class J_AccumulatorMap> . The constructor takes one argument: Class\\ enumClass : The enum type that defines the possible keys. Key methods: createEmptyAccumulators(EnumSet selectedFlows, boolean hasTimeSeries, double signalResolution_h, double duration_h) : Fills the map with accumulators for the given subset of enum keys. All accumulators are created with the same parameters. put(E key, ZeroAccumulator acc) : Adds an individual accumulator for a specific key. get(E key) : Retrieves the accumulator for a given key. getClone() : Returns a deep clone of this map, cloning each accumulator. reset() : Resets all accumulators in the map. clear() : Removes all accumulators from the map. keySet() : Returns the set of keys that have accumulators. Just like the accumulator, it is possible to add or subtract entire accumulator maps (the keys must match). Convenience methods for aggregating over all keys: totalIntegral_kWh() : Sum of getIntegral_kWh() across all accumulators. totalIntegralPos_kWh() : Sum of getIntegralPos_kWh() across all accumulators. totalIntegralNeg_kWh() : Sum of getIntegralNeg_kWh() across all accumulators. totalIntegral_MWh() / totalIntegralPos_MWh() / totalIntegralNeg_MWh() : MWh variants of the above. Accumulator maps can be converted to DataSetMaps via getDataSetMap(startTime_h) or getDataSetMap(startTime_h, dataSetSignalResolution_h) . The latter allows downsampling to a coarser signal resolution, given that it is a multiple of the accumulator's resolution.","title":"Accumulator Maps"},{"location":"engine/data_structures/accumulators/","text":"Accumulators Accumulators are a datastructure created to be able to efficiently store data results of rapidrun simulations. The unit of data inside accumulators is always kW. The accumulator has public methods to inquire about kWh totals (integrals), minima/maxima and a method to convert the timeseries to an AnyLogic DataSet (to render charts / graphs). For a data structure to store data with other units see time series There also exist methods to add and subtract accumulators from eachother. The constructor accepts three arguments: boolean hasTimeSeries : When this boolean is set to true the accumulator will store the entire timeseries. When the boolean is set to false the accumulator will only store specific data about the timeseries, such as the minimum, maximum, and total. double signalResolution_h : This parameter specifies the resolution of the timeseries. The timeseries will store a datapoint for each signalResolution_h. This value must be at least the timestep of the energymodel (15 minutes by default) and can be at most the duration_h. It must also be a divisor of duration_h. double duration_h : The total duration of which we are storing data. For an accumulator that stores data for an entire year this would be 8760 hours, for an accumulator that stores data about one week this would be 672 hours. Every timestep the method addStep should be called with the current power in kW. This method then handles the timeseries and signal resolution.","title":"Accumulators"},{"location":"engine/data_structures/accumulators/#accumulators","text":"Accumulators are a datastructure created to be able to efficiently store data results of rapidrun simulations. The unit of data inside accumulators is always kW. The accumulator has public methods to inquire about kWh totals (integrals), minima/maxima and a method to convert the timeseries to an AnyLogic DataSet (to render charts / graphs). For a data structure to store data with other units see time series There also exist methods to add and subtract accumulators from eachother. The constructor accepts three arguments: boolean hasTimeSeries : When this boolean is set to true the accumulator will store the entire timeseries. When the boolean is set to false the accumulator will only store specific data about the timeseries, such as the minimum, maximum, and total. double signalResolution_h : This parameter specifies the resolution of the timeseries. The timeseries will store a datapoint for each signalResolution_h. This value must be at least the timestep of the energymodel (15 minutes by default) and can be at most the duration_h. It must also be a divisor of duration_h. double duration_h : The total duration of which we are storing data. For an accumulator that stores data for an entire year this would be 8760 hours, for an accumulator that stores data about one week this would be 672 hours. Every timestep the method addStep should be called with the current power in kW. This method then handles the timeseries and signal resolution.","title":"Accumulators"},{"location":"engine/data_structures/data_structures/","text":"Data Structures Data structures are organized ways of storing and managing data. We have implemented several different data structures to fit the needs of our model. These include: Accumulators Accumulator Maps DataSet Maps Flows Maps Profile Pointers Profile Forecasters Time Series Value Maps","title":"Overview"},{"location":"engine/data_structures/data_structures/#data-structures","text":"Data structures are organized ways of storing and managing data. We have implemented several different data structures to fit the needs of our model. These include: Accumulators Accumulator Maps DataSet Maps Flows Maps Profile Pointers Profile Forecasters Time Series Value Maps","title":"Data Structures"},{"location":"engine/data_structures/dataset_maps/","text":"DataSet Maps DataSet Maps store a set of AnyLogic DataSets (XY charts) keyed by an enum type. The implementation is class J_DataSetMap> . DataSet Maps are typically created from accumulator maps via getDataSetMap(startTime_h) , which converts each accumulator's time series to an AnyLogic DataSet for rendering charts and graphs. The constructor accepts one argument: Class\\ enumClass : The enum type that defines the possible keys. Key methods: createEmptyDataSets(EnumSet selectedFlows, int size) : Creates empty DataSets for the given subset of enum keys. put(E key, DataSet ds) : Associates a DataSet with the given key. get(E key) : Retrieves the DataSet for a given key. clear() : Removes all DataSets. keySet() : Returns the set of keys that have associated DataSets.","title":"DataSet Maps"},{"location":"engine/data_structures/dataset_maps/#dataset-maps","text":"DataSet Maps store a set of AnyLogic DataSets (XY charts) keyed by an enum type. The implementation is class J_DataSetMap> . DataSet Maps are typically created from accumulator maps via getDataSetMap(startTime_h) , which converts each accumulator's time series to an AnyLogic DataSet for rendering charts and graphs. The constructor accepts one argument: Class\\ enumClass : The enum type that defines the possible keys. Key methods: createEmptyDataSets(EnumSet selectedFlows, int size) : Creates empty DataSets for the given subset of enum keys. put(E key, DataSet ds) : Associates a DataSet with the given key. get(E key) : Retrieves the DataSet for a given key. clear() : Removes all DataSets. keySet() : Returns the set of keys that have associated DataSets.","title":"DataSet Maps"},{"location":"engine/data_structures/flows_maps/","text":"Flows Maps Flows Maps are a data structure to store energy flows per energy carrier . The implementation is class J_FlowsMap . This data structure is used throughout the simulation to pass flow values at each timestep. For example, the current balance flows, consumption flows, and production flows are all stored as J_FlowsMap objects. Internally the values are stored in a fixed-size double array indexed by the ordinal of OL_EnergyCarriers . An EnumSet tracks which carriers have been set, providing faster iteration than iterating over all possible carriers. The constructor takes no arguments: Default constructor : Prepares an empty flows map with all energy carrier slots initialized to zero. The following methods are available: get(OL_EnergyCarriers key) : Returns the flow value for the given energy carrier. put(OL_EnergyCarriers key, double value) : Sets the flow value for a carrier. addFlow(OL_EnergyCarriers key, double value) : Adds value to the existing flow for a carrier. addFlows(J_FlowsMap f) : Adds all flows from another flows map. removeFlows(J_FlowsMap f) : Subtracts all flows from another flows map. cloneMap(J_FlowsMap flowMap) : Copies all values from another map. clear() : Resets all values to zero. totalSum() : Returns the sum of all flows. Reduced Flows Map There is also a J_ReducedFlowsMap that extends EnumMap . It overrides get(Object key) to return 0.0 instead of null for unset keys. It provides the same addFlow() and addReducedFlows() convenience methods and is used for aggregating flows from multiple J_FlowsMap objects. For a generic version of this data structure (not restricted to OL_EnergyCarriers ) see value maps .","title":"Flows Maps"},{"location":"engine/data_structures/flows_maps/#flows-maps","text":"Flows Maps are a data structure to store energy flows per energy carrier . The implementation is class J_FlowsMap . This data structure is used throughout the simulation to pass flow values at each timestep. For example, the current balance flows, consumption flows, and production flows are all stored as J_FlowsMap objects. Internally the values are stored in a fixed-size double array indexed by the ordinal of OL_EnergyCarriers . An EnumSet tracks which carriers have been set, providing faster iteration than iterating over all possible carriers. The constructor takes no arguments: Default constructor : Prepares an empty flows map with all energy carrier slots initialized to zero. The following methods are available: get(OL_EnergyCarriers key) : Returns the flow value for the given energy carrier. put(OL_EnergyCarriers key, double value) : Sets the flow value for a carrier. addFlow(OL_EnergyCarriers key, double value) : Adds value to the existing flow for a carrier. addFlows(J_FlowsMap f) : Adds all flows from another flows map. removeFlows(J_FlowsMap f) : Subtracts all flows from another flows map. cloneMap(J_FlowsMap flowMap) : Copies all values from another map. clear() : Resets all values to zero. totalSum() : Returns the sum of all flows.","title":"Flows Maps"},{"location":"engine/data_structures/flows_maps/#reduced-flows-map","text":"There is also a J_ReducedFlowsMap that extends EnumMap . It overrides get(Object key) to return 0.0 instead of null for unset keys. It provides the same addFlow() and addReducedFlows() convenience methods and is used for aggregating flows from multiple J_FlowsMap objects. For a generic version of this data structure (not restricted to OL_EnergyCarriers ) see value maps .","title":"Reduced Flows Map"},{"location":"engine/data_structures/profile_forecasters/","text":"Profile Forecasters Profile Forecasters compute a rolling average forecast over a profile pointer . The implementation is class J_ProfileForecaster . A forecaster takes a profile pointer and computes the average value over a configurable forecast horizon. As the simulation progresses, the forecast window slides forward and the average is updated incrementally. The constructor accepts the following arguments: String forecastName : An optional name for this forecaster. If null, it is automatically generated from the profile pointer name and forecast horizon. J_ProfilePointer profilePointer : The underlying profile to forecast over. double forecastTime_h : The length of the forecast horizon in hours. double currentTime_h : The current simulation time used for the initial forecast calculation. double timeStep_h : The simulation time step, used to determine the number of samples in the forecast window. Key methods: initializeForecast(double currentTime_h) : Computes the initial forecast as the average of all profile values from currentTime_h to currentTime_h + forecastTime_h . updateForecast(double t_h) : Updates the forecast by removing the contribution of the value at t_h and adding the contribution of the value at t_h + forecastTime_h (sliding window). getForecast() : Returns the current forecasted average value. getForecastTime_h() : Returns the length of the forecast horizon. getName() : Returns the name of this forecaster. The sliding window update in updateForecast is efficient: it only needs two profile lookups per timestep rather than recomputing the entire average.","title":"Profile Forecasters"},{"location":"engine/data_structures/profile_forecasters/#profile-forecasters","text":"Profile Forecasters compute a rolling average forecast over a profile pointer . The implementation is class J_ProfileForecaster . A forecaster takes a profile pointer and computes the average value over a configurable forecast horizon. As the simulation progresses, the forecast window slides forward and the average is updated incrementally. The constructor accepts the following arguments: String forecastName : An optional name for this forecaster. If null, it is automatically generated from the profile pointer name and forecast horizon. J_ProfilePointer profilePointer : The underlying profile to forecast over. double forecastTime_h : The length of the forecast horizon in hours. double currentTime_h : The current simulation time used for the initial forecast calculation. double timeStep_h : The simulation time step, used to determine the number of samples in the forecast window. Key methods: initializeForecast(double currentTime_h) : Computes the initial forecast as the average of all profile values from currentTime_h to currentTime_h + forecastTime_h . updateForecast(double t_h) : Updates the forecast by removing the contribution of the value at t_h and adding the contribution of the value at t_h + forecastTime_h (sliding window). getForecast() : Returns the current forecasted average value. getForecastTime_h() : Returns the length of the forecast horizon. getName() : Returns the name of this forecaster. The sliding window update in updateForecast is efficient: it only needs two profile lookups per timestep rather than recomputing the entire average.","title":"Profile Forecasters"},{"location":"engine/data_structures/profile_pointers/","text":"Profile Pointers Profile Pointers provide access to time-series input data, such as weather profiles (temperature, irradiance, wind speed) or market prices. The implementation is class J_ProfilePointer . Unlike Accumulators and Time Series which store simulation results , profile pointers read pre-defined input profiles. The profile data is stored as a double[] array with a fixed timestep. The constructor accepts the following arguments: String name : A descriptive name for this profile (e.g. \"temperature\", \"electricity_price\"). double[] profile : The array of data values. double dataTimeStep_h : The time step between consecutive values in the profile array. double dataStartTime_h : The start time of the first profile entry, relative to 00:00 on January 1st of the simulation year. OL_ProfileUnits profileUnits : The physical unit of the profile values. Key methods: getValue(double time_h) : Returns the profile value at the given simulation time. Supports profile looping: when enableProfileLooping is true (default), indices beyond the array length wrap around using modulo arithmetic. updateValue(double t_h) : Calls getValue(t_h) and stores the result internally. getCurrentValue() : Returns the most recently updated value. getAllValues() : Returns a clone of the full profile array. getDataTimeStep_h() : Returns the time step of the profile data. The updateValue / getCurrentValue pattern is typically used each timestep during the simulation to avoid repeated index calculations. For forecasting over a profile, see profile forecasters .","title":"Profile Pointers"},{"location":"engine/data_structures/profile_pointers/#profile-pointers","text":"Profile Pointers provide access to time-series input data, such as weather profiles (temperature, irradiance, wind speed) or market prices. The implementation is class J_ProfilePointer . Unlike Accumulators and Time Series which store simulation results , profile pointers read pre-defined input profiles. The profile data is stored as a double[] array with a fixed timestep. The constructor accepts the following arguments: String name : A descriptive name for this profile (e.g. \"temperature\", \"electricity_price\"). double[] profile : The array of data values. double dataTimeStep_h : The time step between consecutive values in the profile array. double dataStartTime_h : The start time of the first profile entry, relative to 00:00 on January 1st of the simulation year. OL_ProfileUnits profileUnits : The physical unit of the profile values. Key methods: getValue(double time_h) : Returns the profile value at the given simulation time. Supports profile looping: when enableProfileLooping is true (default), indices beyond the array length wrap around using modulo arithmetic. updateValue(double t_h) : Calls getValue(t_h) and stores the result internally. getCurrentValue() : Returns the most recently updated value. getAllValues() : Returns a clone of the full profile array. getDataTimeStep_h() : Returns the time step of the profile data. The updateValue / getCurrentValue pattern is typically used each timestep during the simulation to avoid repeated index calculations. For forecasting over a profile, see profile forecasters .","title":"Profile Pointers"},{"location":"engine/data_structures/time_series/","text":"Time Series The class ZeroTimeSeries is almost completely analogous to the Accumulator except that it does not require the entries to have the unit kW (any unit can be used). It is different in the following ways: The time series class always stores the full time series as a double[] array, whereas this is optional for the accumulator. The time series stores only one value per signal resolution entry (no averaging of sub-steps when resolution differs from the simulation timestep \u2014 it uses a sample weight instead). There is no 'map' variant of the time series object to conveniently store multiple series for different energy carriers or other option lists, as this has not been needed. The time series provides getSum() , getSumPos() , and getSumNeg() methods (raw sums of the time series values), whereas the accumulator provides integrals in kWh. The constructor accepts two arguments: double signalResolution_h : The resolution of the time series. Must be at least the simulation timestep. double duration_h : The total duration for which data is stored. Key methods: addStep(double value) : Adds a data point for the current time step. getSum() / getSumPos() / getSumNeg() : Returns the sum, positive sum, or negative sum of all values. getTimeSeries() : Returns the underlying double[] array. getMax() / getMin() : Returns the maximum/minimum value. getDataSet(double startTime_h) : Converts the time series to an AnyLogic DataSet for charting. add(ZeroTimeSeries zts) / subtract(ZeroTimeSeries zts) : Element-wise addition/subtraction of time series. The time series object is used to store simulation results. Compare this to the profile pointer , which also stores a series of data points, but these are input data like weather data or market prices.","title":"Time Series"},{"location":"engine/data_structures/time_series/#time-series","text":"The class ZeroTimeSeries is almost completely analogous to the Accumulator except that it does not require the entries to have the unit kW (any unit can be used). It is different in the following ways: The time series class always stores the full time series as a double[] array, whereas this is optional for the accumulator. The time series stores only one value per signal resolution entry (no averaging of sub-steps when resolution differs from the simulation timestep \u2014 it uses a sample weight instead). There is no 'map' variant of the time series object to conveniently store multiple series for different energy carriers or other option lists, as this has not been needed. The time series provides getSum() , getSumPos() , and getSumNeg() methods (raw sums of the time series values), whereas the accumulator provides integrals in kWh. The constructor accepts two arguments: double signalResolution_h : The resolution of the time series. Must be at least the simulation timestep. double duration_h : The total duration for which data is stored. Key methods: addStep(double value) : Adds a data point for the current time step. getSum() / getSumPos() / getSumNeg() : Returns the sum, positive sum, or negative sum of all values. getTimeSeries() : Returns the underlying double[] array. getMax() / getMin() : Returns the maximum/minimum value. getDataSet(double startTime_h) : Converts the time series to an AnyLogic DataSet for charting. add(ZeroTimeSeries zts) / subtract(ZeroTimeSeries zts) : Element-wise addition/subtraction of time series. The time series object is used to store simulation results. Compare this to the profile pointer , which also stores a series of data points, but these are input data like weather data or market prices.","title":"Time Series"},{"location":"engine/data_structures/value_maps/","text":"Value Maps Value Maps are a generic data structure for storing a double value for each key in an enum set. The implementation is class J_ValueMap> . Internally the values are stored in a flat array indexed by the enum ordinal. An EnumSet tracks which keys have been set. This makes value maps more memory-efficient and faster than using a HashMap or EnumMap . The constructor accepts the enum Class : Class\\ enumClass : The enum type that defines the possible keys. All enum constants are pre-allocated in the internal array. The following methods are available: get(E key) : Returns the current value for the given key. put(E key, double value) : Sets the value for the given key. addFlow(E key, double value) : Adds value to the existing value for the key. addFlows(J_ValueMap f) : Adds all values from another value map. removeFlows(J_ValueMap f) : Subtracts all values from another value map. cloneMap(J_ValueMap flowMap) : Copies all values from another map. clear() : Resets all values to zero. totalSum() : Returns the sum of all values. Value Maps are similar to Flows Maps , but are generic over any enum type, whereas flows maps are specifically for OL_EnergyCarriers .","title":"Value Maps"},{"location":"engine/data_structures/value_maps/#value-maps","text":"Value Maps are a generic data structure for storing a double value for each key in an enum set. The implementation is class J_ValueMap> . Internally the values are stored in a flat array indexed by the enum ordinal. An EnumSet tracks which keys have been set. This makes value maps more memory-efficient and faster than using a HashMap or EnumMap . The constructor accepts the enum Class : Class\\ enumClass : The enum type that defines the possible keys. All enum constants are pre-allocated in the internal array. The following methods are available: get(E key) : Returns the current value for the given key. put(E key, double value) : Sets the value for the given key. addFlow(E key, double value) : Adds value to the existing value for the key. addFlows(J_ValueMap f) : Adds all values from another value map. removeFlows(J_ValueMap f) : Subtracts all values from another value map. cloneMap(J_ValueMap flowMap) : Copies all values from another map. clear() : Resets all values to zero. totalSum() : Returns the sum of all values. Value Maps are similar to Flows Maps , but are generic over any enum type, whereas flows maps are specifically for OL_EnergyCarriers .","title":"Value Maps"},{"location":"interface/overview/","text":"Interface","title":"Overview"},{"location":"interface/overview/#interface","text":"","title":"Interface"},{"location":"loader/overview/","text":"Loader","title":"Overview"},{"location":"loader/overview/#loader","text":"","title":"Loader"},{"location":"loader/lombok/lombok/","text":"Lombok in AnyLogic Installation Project Lombok can do code generation to improve the experience of working with Java code. It can add common patterns like builder classes, value classes, null checks, and getters. To use it in AnyLogic: 1. Download lombok.jar and place it in the AnyLogic directory, for example C:\\Program Files\\AnyLogic 8.9 Personal Learning Edition\\lombok.jar 2. Add the line below to AnyLogic.ini in the same directory. To do this in Windows, run notepad as Administrator and then navigate to the file via \"File\" > \"Open\". -javaagent:./lombok.jar AnyLogic.ini should look like this: -vmargs -Xmx4096M -Djava.util.Arrays.useLegacyMergeSort=true --add-modules=ALL-SYSTEM -Dorg.eclipse.e4.ui.css.theme.disableOSDarkThemeInherit=true -Dsun.java2d.ddscale=true -Dsun.java2d.translaccel=true --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED -javaagent:./lombok.jar 3. Add lombok.jar to your project's dependencies. 4. If you have a custom launch script ( .bat , .sh ) it may not find lombok.jar . To fix it you can place the launch script in the AnyLogic directory. set CLIENT_ID=xxx set CLIENT_SECRET=xxx Anylogic.exe 5. You can now use the annotations in your project. Using @Builder for Agents You may want to use Lombok outside of plain Java code. To create a builder class for an Agent, add these annotations to the bottom of the imports section of that Agent: @lombok.AllArgsConstructor @lombok.Builder Use it like so:","title":"Lombok"},{"location":"loader/lombok/lombok/#lombok-in-anylogic","text":"","title":"Lombok in AnyLogic"},{"location":"loader/lombok/lombok/#installation","text":"Project Lombok can do code generation to improve the experience of working with Java code. It can add common patterns like builder classes, value classes, null checks, and getters. To use it in AnyLogic: 1. Download lombok.jar and place it in the AnyLogic directory, for example C:\\Program Files\\AnyLogic 8.9 Personal Learning Edition\\lombok.jar 2. Add the line below to AnyLogic.ini in the same directory. To do this in Windows, run notepad as Administrator and then navigate to the file via \"File\" > \"Open\". -javaagent:./lombok.jar AnyLogic.ini should look like this: -vmargs -Xmx4096M -Djava.util.Arrays.useLegacyMergeSort=true --add-modules=ALL-SYSTEM -Dorg.eclipse.e4.ui.css.theme.disableOSDarkThemeInherit=true -Dsun.java2d.ddscale=true -Dsun.java2d.translaccel=true --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED -javaagent:./lombok.jar 3. Add lombok.jar to your project's dependencies. 4. If you have a custom launch script ( .bat , .sh ) it may not find lombok.jar . To fix it you can place the launch script in the AnyLogic directory. set CLIENT_ID=xxx set CLIENT_SECRET=xxx Anylogic.exe 5. You can now use the annotations in your project.","title":"Installation"},{"location":"loader/lombok/lombok/#using-builder-for-agents","text":"You may want to use Lombok outside of plain Java code. To create a builder class for an Agent, add these annotations to the bottom of the imports section of that Agent: @lombok.AllArgsConstructor @lombok.Builder Use it like so:","title":"Using @Builder for Agents"},{"location":"resultsUI/overview/","text":"Results UI","title":"Overview"},{"location":"resultsUI/overview/#results-ui","text":"","title":"Results UI"}]}
\ No newline at end of file
+{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Welcome to the LUX Model Documentation LUX Energy Twin (LUX for short) is an open-source, interactive, agent based model that simulates energy systems with a focus on electricity and the electricity grid. Example models to play around with can be found here on our website lux.energy LUX is built inside AnyLogic a multi-method simulation software platform that supports agent based modelling. A free version of this software called 'Personal Learning Edition' can be downloaded and is able to run the LUX models. LUX is written almost entirely in Java. The current AnyLogic version used is 8.9.7 and this uses Java 17. LUX makes use of many public datasets to make sure our models are always enriched with the best data. What LUX can and cannot do LUX does not simulate current and voltage, only power (kW) and power balance. Network lines (cables) are treated as a 'copper plate'. Substations and transformers have limited capacity. This means congestion can only occur at these nodes, not in cables. There is no infrastructure for energy carriers other than electricity. It is possible to simulate storages and buffers of other energy carriers, such as heat or hydrogen. Our models always have a live simulation that plays when the model first boots up and a rapid run simulation that can simulate headless. The live simulation shows the user direct feedback on his actions like changing scenario's or adding and removing assets. The rapidrun simulation is used to calculate and compare KPIs in a meaningful way. The model works in discrete timesteps. The default timestep of the simulation is 15 minute intervals. It is currently not recommend to change this parameter as it is not well tested at different settings. The duration of the simulation can be changed, but simulations longer than one year are currently not supported. 1 Every LUX model consists of 4 packages. Engine: Docs , Github Loader/Interface: Docs , Github ResultsUI: Docs , Github Project: Docs , Github The first three are public repositories that need not be altered for standard models. The fourth is a project specific package. These are not made public because of the sensitive data they contain. A template is made available that can be cloned and set up for your own projects. Simulations of at least two years are on the development roadmap as current Groepstransportoverenkomsten (GTO) calculations from grid operators are based on the previous two years. \u21a9","title":"Home"},{"location":"#welcome-to-the-lux-model-documentation","text":"LUX Energy Twin (LUX for short) is an open-source, interactive, agent based model that simulates energy systems with a focus on electricity and the electricity grid. Example models to play around with can be found here on our website lux.energy LUX is built inside AnyLogic a multi-method simulation software platform that supports agent based modelling. A free version of this software called 'Personal Learning Edition' can be downloaded and is able to run the LUX models. LUX is written almost entirely in Java. The current AnyLogic version used is 8.9.7 and this uses Java 17. LUX makes use of many public datasets to make sure our models are always enriched with the best data.","title":"Welcome to the LUX Model Documentation"},{"location":"#what-lux-can-and-cannot-do","text":"LUX does not simulate current and voltage, only power (kW) and power balance. Network lines (cables) are treated as a 'copper plate'. Substations and transformers have limited capacity. This means congestion can only occur at these nodes, not in cables. There is no infrastructure for energy carriers other than electricity. It is possible to simulate storages and buffers of other energy carriers, such as heat or hydrogen. Our models always have a live simulation that plays when the model first boots up and a rapid run simulation that can simulate headless. The live simulation shows the user direct feedback on his actions like changing scenario's or adding and removing assets. The rapidrun simulation is used to calculate and compare KPIs in a meaningful way. The model works in discrete timesteps. The default timestep of the simulation is 15 minute intervals. It is currently not recommend to change this parameter as it is not well tested at different settings. The duration of the simulation can be changed, but simulations longer than one year are currently not supported. 1 Every LUX model consists of 4 packages. Engine: Docs , Github Loader/Interface: Docs , Github ResultsUI: Docs , Github Project: Docs , Github The first three are public repositories that need not be altered for standard models. The fourth is a project specific package. These are not made public because of the sensitive data they contain. A template is made available that can be cloned and set up for your own projects. Simulations of at least two years are on the development roadmap as current Groepstransportoverenkomsten (GTO) calculations from grid operators are based on the previous two years. \u21a9","title":"What LUX can and cannot do"},{"location":"engine/consistency_checks/","text":"Consistency Checks The LUX engine applies several consistency checks to ensure a correct model. Configuration Check The configuration check validates the model setup before simulation. It is implemented as f_checkConfiguration() methods on the EnergyModel and GridConnections . The EnergyModel's f_checkConfiguration() iterates over all GridConnections and calls their individual check. The GridConnection's f_checkConfiguration() checks for: Flex assets without an EMS : If a GridConnection has flexible assets ( c_flexAssets ) but no I_EnergyManagement (EMS) is configured, a RuntimeException is thrown. EMS-level validation : If an EMS is present, the check is delegated to the EMS's own checkConfiguration() method. Each EMS implementation validates that the set of flex assets matches its expected types. This ensures that every agent with flexible assets has a valid control system assigned before the simulation runs. Energy Balance Check The energy balance check (implemented as f_performEnergyBalanceCheck() on the EnergyModel) verifies the law of conservation of energy: energy cannot be created or destroyed in the model. Energy can only enter or leave the model through these paths: Import of energy carriers. Export of energy carriers. Primary production : Energy harvested from the environment (e.g. wind, solar irradiation, ambient heat absorbed by buildings). Final consumption : Energy that leaves the system as losses (dissipated heat, conversion losses, consumption profiles). The balance equation is: Production - Export = Consumption - Import In code, the check computes: double energyBalanceCheck_MWh = totalImport_MWh + totalProduction_MWh - (totalExport_MWh + totalConsumption_MWh + totalDeltaStoredEnergy_MWh); This value must be zero. If it exceeds a tolerance of 1e-6 MWh, a warning is logged. The check also accounts for changes in stored energy (battery charge state, thermal storage in buildings) to prevent false positives from energy buffers that the same at the end of the simulation compared to the start.","title":"Consistency Checks"},{"location":"engine/consistency_checks/#consistency-checks","text":"The LUX engine applies several consistency checks to ensure a correct model.","title":"Consistency Checks"},{"location":"engine/consistency_checks/#configuration-check","text":"The configuration check validates the model setup before simulation. It is implemented as f_checkConfiguration() methods on the EnergyModel and GridConnections . The EnergyModel's f_checkConfiguration() iterates over all GridConnections and calls their individual check. The GridConnection's f_checkConfiguration() checks for: Flex assets without an EMS : If a GridConnection has flexible assets ( c_flexAssets ) but no I_EnergyManagement (EMS) is configured, a RuntimeException is thrown. EMS-level validation : If an EMS is present, the check is delegated to the EMS's own checkConfiguration() method. Each EMS implementation validates that the set of flex assets matches its expected types. This ensures that every agent with flexible assets has a valid control system assigned before the simulation runs.","title":"Configuration Check"},{"location":"engine/consistency_checks/#energy-balance-check","text":"The energy balance check (implemented as f_performEnergyBalanceCheck() on the EnergyModel) verifies the law of conservation of energy: energy cannot be created or destroyed in the model. Energy can only enter or leave the model through these paths: Import of energy carriers. Export of energy carriers. Primary production : Energy harvested from the environment (e.g. wind, solar irradiation, ambient heat absorbed by buildings). Final consumption : Energy that leaves the system as losses (dissipated heat, conversion losses, consumption profiles). The balance equation is: Production - Export = Consumption - Import In code, the check computes: double energyBalanceCheck_MWh = totalImport_MWh + totalProduction_MWh - (totalExport_MWh + totalConsumption_MWh + totalDeltaStoredEnergy_MWh); This value must be zero. If it exceeds a tolerance of 1e-6 MWh, a warning is logged. The check also accounts for changes in stored energy (battery charge state, thermal storage in buildings) to prevent false positives from energy buffers that the same at the end of the simulation compared to the start.","title":"Energy Balance Check"},{"location":"engine/energy_assets/","text":"Energy Assets EnergyAssets are a core class in the LUX model. Everything that produces, consumes or converts energy in the model is an energy asset. The energy assets in the model have a hierarchical structure. At the top of the tree is the distinction between J_EAFixed and J_EAFlex. Fixed assets are assets that have predetermined behaviour. These are 'profiles' that are played during the simulation. An example for a fixed asset is the baseload consumption of a household or the production of a solar panel. There can be flexibility in these assets, for example by curtailing the solar power, but a priori there is none. Flex assets are assets that require, at every timestep, to be told at what power they are operated. This decision is made by an EMS The full tree of the hierarchical structure of energy assets can be seen in image X. Energy assets have two important option lists : energyAssetType: This determines the category of the energy asset. This optionlist can seem redundant 1 because of the different classes, but allows us to use data such as profiles of EV charging sessions and keep the bookkeeping consistent with simulated J_EAEVs. assetFlowCategory: This determines under which category the energy flows of this asset fall in the graphs and charts When energyassets are created they register themselves at their GridConnection through the method registerEnergyAsset(). At every timestep the assets are operated through the method f_updateAllFlows(). At the start of a rapidrun the current state of the asset in the live simulation is stored with the method storeStatesAndReset(), at the end of the headless run the states are restored through restoreStates(). Energy assets also keep track of a variable called 'EnergyUsed_kWh', this variable contains all the energy losses of the asset. At the end of a rapidrun simulation these losses are compared to the bookkeeping of the gridconnection and energymodel to make sure no energy has disappeared or is created out of thin air. See also Consistency Checks We are actually trying to remove the optionlist OL_EnergyAssetType, because it has exploded too much in size and are currently looking into ways to split this into multiple smaller option lists like OL_ProductionType, OL_VehicleType, etc. \u21a9","title":"Energy Assets"},{"location":"engine/energy_assets/#energy-assets","text":"EnergyAssets are a core class in the LUX model. Everything that produces, consumes or converts energy in the model is an energy asset. The energy assets in the model have a hierarchical structure. At the top of the tree is the distinction between J_EAFixed and J_EAFlex. Fixed assets are assets that have predetermined behaviour. These are 'profiles' that are played during the simulation. An example for a fixed asset is the baseload consumption of a household or the production of a solar panel. There can be flexibility in these assets, for example by curtailing the solar power, but a priori there is none. Flex assets are assets that require, at every timestep, to be told at what power they are operated. This decision is made by an EMS The full tree of the hierarchical structure of energy assets can be seen in image X. Energy assets have two important option lists : energyAssetType: This determines the category of the energy asset. This optionlist can seem redundant 1 because of the different classes, but allows us to use data such as profiles of EV charging sessions and keep the bookkeeping consistent with simulated J_EAEVs. assetFlowCategory: This determines under which category the energy flows of this asset fall in the graphs and charts When energyassets are created they register themselves at their GridConnection through the method registerEnergyAsset(). At every timestep the assets are operated through the method f_updateAllFlows(). At the start of a rapidrun the current state of the asset in the live simulation is stored with the method storeStatesAndReset(), at the end of the headless run the states are restored through restoreStates(). Energy assets also keep track of a variable called 'EnergyUsed_kWh', this variable contains all the energy losses of the asset. At the end of a rapidrun simulation these losses are compared to the bookkeeping of the gridconnection and energymodel to make sure no energy has disappeared or is created out of thin air. See also Consistency Checks We are actually trying to remove the optionlist OL_EnergyAssetType, because it has exploded too much in size and are currently looking into ways to split this into multiple smaller option lists like OL_ProductionType, OL_VehicleType, etc. \u21a9","title":"Energy Assets"},{"location":"engine/energy_carriers/","text":"Energy Carriers The energycarriers in LUX are found in the optionlist OL_EnergyCarriers in the engine. By default this optionlist contains the following energycarriers: Electricity Heat Methane Petroleum_fuel Hydrogen Iron_powder Other energycarriers can be easily added to the optionlist. All the datastructures, such as the accumulators in maps in the rapidrundata, that store data for charts and graphs are dynamically extended to include these new energycarriers. The engine keeps track of which energycarriers are used in the model. This is done through the EnumSets activeProductionEnergyCarriers and activeConsumptionEnergyCarriers in the energy assets.","title":"Energy Carriers"},{"location":"engine/energy_carriers/#energy-carriers","text":"The energycarriers in LUX are found in the optionlist OL_EnergyCarriers in the engine. By default this optionlist contains the following energycarriers: Electricity Heat Methane Petroleum_fuel Hydrogen Iron_powder Other energycarriers can be easily added to the optionlist. All the datastructures, such as the accumulators in maps in the rapidrundata, that store data for charts and graphs are dynamically extended to include these new energycarriers. The engine keeps track of which energycarriers are used in the model. This is done through the EnumSets activeProductionEnergyCarriers and activeConsumptionEnergyCarriers in the energy assets.","title":"Energy Carriers"},{"location":"engine/energy_coops/","text":"Energy Cooperatives Energy cooperatives (or EnergyCoops for short) have two separate use cases in the engine. The traditional meaning: a community-owned cooperative that offers a sustainable, community-focused alternative to traditional energy providers. As a collection of GridConnections , usually businesses, that form an Energy Hub to share energy and/or contracted capacity. The EnergyCoop agent implements I_EnergyData , exposing rapid-run and live data for results visualization. It extends the Actor class. Key fields: c_memberGridConnections / c_customerGridConnections : GridConnections belonging to the cooperative as members (producers) or customers (consumers). In an E-Hub all gridconnections are members. f_calculateEnergyBalance : This function is the main part of the engine loop every timestep. It resets the energy flows, loops through the coop members and customers to aggregate the energy flows. Then it stores the results in either the live data or rapidrun data class. f_operateAggregatorEnergyManagement : This function is called by the energymodel after all gridconnections have operated their assets and will determine the behaviour for the aggregated assets for the next timestep. This means aggregated assets in an EnergyCoop will always have one timestep delay in their behaviour. The EnergyCoop agent allows for a centralized EMS that takes control from individual GridConnections and manages all (or a subset of) the flexible assets from a single point. This allows members of an Energy Hub to use more of their existing connection capacities or increase their combined self-consumption. An example of an Energy Cooperative model developed with LUX is the Cooperatie Configurator . Models about Energy Hubs are usually restricted in their access because of the sensitive company data.","title":"Energy Cooperatives"},{"location":"engine/energy_coops/#energy-cooperatives","text":"Energy cooperatives (or EnergyCoops for short) have two separate use cases in the engine. The traditional meaning: a community-owned cooperative that offers a sustainable, community-focused alternative to traditional energy providers. As a collection of GridConnections , usually businesses, that form an Energy Hub to share energy and/or contracted capacity. The EnergyCoop agent implements I_EnergyData , exposing rapid-run and live data for results visualization. It extends the Actor class. Key fields: c_memberGridConnections / c_customerGridConnections : GridConnections belonging to the cooperative as members (producers) or customers (consumers). In an E-Hub all gridconnections are members. f_calculateEnergyBalance : This function is the main part of the engine loop every timestep. It resets the energy flows, loops through the coop members and customers to aggregate the energy flows. Then it stores the results in either the live data or rapidrun data class. f_operateAggregatorEnergyManagement : This function is called by the energymodel after all gridconnections have operated their assets and will determine the behaviour for the aggregated assets for the next timestep. This means aggregated assets in an EnergyCoop will always have one timestep delay in their behaviour. The EnergyCoop agent allows for a centralized EMS that takes control from individual GridConnections and manages all (or a subset of) the flexible assets from a single point. This allows members of an Energy Hub to use more of their existing connection capacities or increase their combined self-consumption. An example of an Energy Cooperative model developed with LUX is the Cooperatie Configurator . Models about Energy Hubs are usually restricted in their access because of the sensitive company data.","title":"Energy Cooperatives"},{"location":"engine/energy_data/","text":"EnergyData I_EnergyData is an interface implemented by three agents: GridConnections EnergyCoops EnergyModel The interface specifies 4 methods: * getLiveData() * getRapidRunData() * getPreviousRapidRunData() * getScope() This allows the resultsUI to request data for charts and graphs from different agents in the engine in a standerdized method. The data stored in GridNodes and their available charts differ too much to be included in this list. The agent EnergyDataViewer is used when debugging to inspect the data in the live and rapidrun classes. A button labeled 'View Data' is available on the canvasses of the three agents to take fill the data viewer and navigate to it.","title":"Energy Data"},{"location":"engine/energy_data/#energydata","text":"I_EnergyData is an interface implemented by three agents: GridConnections EnergyCoops EnergyModel The interface specifies 4 methods: * getLiveData() * getRapidRunData() * getPreviousRapidRunData() * getScope() This allows the resultsUI to request data for charts and graphs from different agents in the engine in a standerdized method. The data stored in GridNodes and their available charts differ too much to be included in this list. The agent EnergyDataViewer is used when debugging to inspect the data in the live and rapidrun classes. A button labeled 'View Data' is available on the canvasses of the three agents to take fill the data viewer and navigate to it.","title":"EnergyData"},{"location":"engine/energy_management_systems/","text":"Energy Management Systems The Energy Management System (EMS) lives inside each GridConnection and decides what all the flexible assets do at every timestep. The interface is I_EnergyManagement . There are three built-in implementations: J_EnergyManagementDefault The default EMS that delegates to external sub-managers, calls them in the following order each timestep: Heating ( I_HeatingManagement ) \u2014 controls heat pumps and heating systems. Charging ( I_ChargingManagement ) \u2014 manages EV charging sessions. Battery ( I_BatteryManagement ) \u2014 operates stationary battery storage. Backup Generator ( I_BackupGeneratorManagement ) \u2014 runs backup generators if needed. Curtailment ( I_CurtailManagement ) \u2014 curtails production when required. 2f 2f 2f 2f v werfvc werfvc werfvc werfvc v q3ewrf q3ewrf q3ewrf q3ewrf v 43f 43f 43f 43f v 43f 43f 43f 43f v 43 43 43 43 v f43 f43 f43 f43 v f f f f v 43f34 43f34 43f34 43f34 v v Custom EMS You can implement your own EMS by implementing the I_EnergyManagement interface. The interface specifies: manageFlexAssets(J_TimeVariables) : The main scheduling method called each timestep. checkConfiguration(List) : Validates that the set of flex assets is compatible with this EMS. getInternalAssetManagements() / getSupportedExternalAssetManagements() / getActiveExternalAssetManagements() : Provide and track the allowed sub-managers. setExternalAssetManagement(...) / removeExternalAssetManagement(...) : Add or remove sub-managers dynamically. Each EMS has a certain incentive \u2014 for example maximizing self-consumption from solar panels or reducing peak import from the grid. Systems can also differ in their approach: some decide at every timestep what to do in that same timestep, while others make a schedule based on a forecast.","title":"Energy Management Systems"},{"location":"engine/energy_management_systems/#energy-management-systems","text":"The Energy Management System (EMS) lives inside each GridConnection and decides what all the flexible assets do at every timestep. The interface is I_EnergyManagement . There are three built-in implementations:","title":"Energy Management Systems"},{"location":"engine/energy_management_systems/#j_energymanagementdefault","text":"The default EMS that delegates to external sub-managers, calls them in the following order each timestep: Heating ( I_HeatingManagement ) \u2014 controls heat pumps and heating systems. Charging ( I_ChargingManagement ) \u2014 manages EV charging sessions. Battery ( I_BatteryManagement ) \u2014 operates stationary battery storage. Backup Generator ( I_BackupGeneratorManagement ) \u2014 runs backup generators if needed. Curtailment ( I_CurtailManagement ) \u2014 curtails production when required. 2f 2f 2f 2f v werfvc werfvc werfvc werfvc v q3ewrf q3ewrf q3ewrf q3ewrf v 43f 43f 43f 43f v 43f 43f 43f 43f v 43 43 43 43 v f43 f43 f43 f43 v f f f f v 43f34 43f34 43f34 43f34 v v","title":"J_EnergyManagementDefault"},{"location":"engine/energy_management_systems/#custom-ems","text":"You can implement your own EMS by implementing the I_EnergyManagement interface. The interface specifies: manageFlexAssets(J_TimeVariables) : The main scheduling method called each timestep. checkConfiguration(List) : Validates that the set of flex assets is compatible with this EMS. getInternalAssetManagements() / getSupportedExternalAssetManagements() / getActiveExternalAssetManagements() : Provide and track the allowed sub-managers. setExternalAssetManagement(...) / removeExternalAssetManagement(...) : Add or remove sub-managers dynamically. Each EMS has a certain incentive \u2014 for example maximizing self-consumption from solar panels or reducing peak import from the grid. Systems can also differ in their approach: some decide at every timestep what to do in that same timestep, while others make a schedule based on a forecast.","title":"Custom EMS"},{"location":"engine/energy_model/","text":"Energy Model The EnergyModel is the top-level simulation agent of the engine . It orchestrates the entire simulation by managing all other agent populations \u2014 GridConnections , GridNodes , and EnergyCoops \u2014 and stepping through time. The EnergyModel is also where all energy flows of all agents in the model accumulate at each timestep. The following key collections are held by the EnergyModel: c_gridConnections : All GridConnections in the simulation. c_gridNodesTopLevel / c_gridNodesNotTopLevel / c_gridNodesHeat : The GridNode collections organized by hierarchy and energy carrier. c_energyAssets / c_productionAssets / c_storageAssets / c_ambientDependentAssets : Asset collections for iteration and management. The EnergyModel holds time parameters ( J_TimeParameters ) and time variables ( J_TimeVariables ) as well as profile pointers, like those for weather and pricing data: pp_ambientTemperature_degC : Ambient temperature profile. pp_windProduction_fr : Wind production factor profile. pp_dayAheadElectricityPricing_eurpMWh : Day-ahead electricity price profile. The engine runs two types of simulations: Live Simulation (interactive feedback) and RapidRun Simulation (batch comparison of scenarios).","title":"Energy Model"},{"location":"engine/energy_model/#energy-model","text":"The EnergyModel is the top-level simulation agent of the engine . It orchestrates the entire simulation by managing all other agent populations \u2014 GridConnections , GridNodes , and EnergyCoops \u2014 and stepping through time. The EnergyModel is also where all energy flows of all agents in the model accumulate at each timestep. The following key collections are held by the EnergyModel: c_gridConnections : All GridConnections in the simulation. c_gridNodesTopLevel / c_gridNodesNotTopLevel / c_gridNodesHeat : The GridNode collections organized by hierarchy and energy carrier. c_energyAssets / c_productionAssets / c_storageAssets / c_ambientDependentAssets : Asset collections for iteration and management. The EnergyModel holds time parameters ( J_TimeParameters ) and time variables ( J_TimeVariables ) as well as profile pointers, like those for weather and pricing data: pp_ambientTemperature_degC : Ambient temperature profile. pp_windProduction_fr : Wind production factor profile. pp_dayAheadElectricityPricing_eurpMWh : Day-ahead electricity price profile. The engine runs two types of simulations: Live Simulation (interactive feedback) and RapidRun Simulation (batch comparison of scenarios).","title":"Energy Model"},{"location":"engine/grid_connections/","text":"GridConnections GridConnections are agents that represent a connection to the grid. These are usually homes or companies, but could also be solar fields, windmills, charging stations, large-scale batteries, or district heating heat sources. Parameters: p_gridConnectionID : A unique string to identify the GridConnection. p_address : A class containing address details (postal code, street name, house number, etc.). p_energyManagement : The EMS ( I_EnergyManagement ) controlling the flexible assets. p_parentNodeElectricID / p_parentNodeHeatID : The IDs of the parent GridNodes for electricity and heat. Metadata: v_liveConnectionMetaData : Contains the contracted delivery/feed-in capacity, the physical capacity, and whether this information is known or estimated. v_liveAssetsMetaData : Metadata about the assets (active flow categories, installed capacities). Key methods: f_updateFlexAssetFlows() : Called by the EMS to operate the flexible energy assets. f_connectToJ_EA(J_EAFixed) / f_removeTheJ_EAFixed(J_EAFixed) : Add and remove energy assets. f_calculateEnergyBalance() : Part of the main simulation loop. Called by the EnergyModel at every timestep. Resets all per-timestep values, then manages and operates all assets. f_connectionMetering() : Called at the end of f_calculateEnergyBalance . Checks for heat imbalances (which would stop the simulation), then stores the timestep data in the live or rapid-run data classes.","title":"Grid Connections"},{"location":"engine/grid_connections/#gridconnections","text":"GridConnections are agents that represent a connection to the grid. These are usually homes or companies, but could also be solar fields, windmills, charging stations, large-scale batteries, or district heating heat sources. Parameters: p_gridConnectionID : A unique string to identify the GridConnection. p_address : A class containing address details (postal code, street name, house number, etc.). p_energyManagement : The EMS ( I_EnergyManagement ) controlling the flexible assets. p_parentNodeElectricID / p_parentNodeHeatID : The IDs of the parent GridNodes for electricity and heat. Metadata: v_liveConnectionMetaData : Contains the contracted delivery/feed-in capacity, the physical capacity, and whether this information is known or estimated. v_liveAssetsMetaData : Metadata about the assets (active flow categories, installed capacities). Key methods: f_updateFlexAssetFlows() : Called by the EMS to operate the flexible energy assets. f_connectToJ_EA(J_EAFixed) / f_removeTheJ_EAFixed(J_EAFixed) : Add and remove energy assets. f_calculateEnergyBalance() : Part of the main simulation loop. Called by the EnergyModel at every timestep. Resets all per-timestep values, then manages and operates all assets. f_connectionMetering() : Called at the end of f_calculateEnergyBalance . Checks for heat imbalances (which would stop the simulation), then stores the timestep data in the live or rapid-run data classes.","title":"GridConnections"},{"location":"engine/grid_nodes/","text":"GridNodes GridNodes are part of either the electricity or heat grid, depending on the value of p_energyCarrier . They form a hierarchical tree structure \u2014 the model does not support rings in the gridnode topology. Parameters: p_gridNodeID : A unique identifier (e.g. T0, T1, T2). p_energyCarrier : The OL_EnergyCarriers type for this node (electricity or heat). p_capacity_kW : The symmetrical capacity of this grid node. p_realCapacityAvailable : Whether the capacity is known or estimated. p_parentNodeID : The ID of the parent node in the tree. Collections: c_connectedGridNodes : Child GridNodes connected below this node. c_connectedGridConnections : GridConnections connected to this node. c_energyCoops : EnergyCoops at this node.","title":"Grid Nodes"},{"location":"engine/grid_nodes/#gridnodes","text":"GridNodes are part of either the electricity or heat grid, depending on the value of p_energyCarrier . They form a hierarchical tree structure \u2014 the model does not support rings in the gridnode topology. Parameters: p_gridNodeID : A unique identifier (e.g. T0, T1, T2). p_energyCarrier : The OL_EnergyCarriers type for this node (electricity or heat). p_capacity_kW : The symmetrical capacity of this grid node. p_realCapacityAvailable : Whether the capacity is known or estimated. p_parentNodeID : The ID of the parent node in the tree. Collections: c_connectedGridNodes : Child GridNodes connected below this node. c_connectedGridConnections : GridConnections connected to this node. c_energyCoops : EnergyCoops at this node.","title":"GridNodes"},{"location":"engine/option_lists/","text":"OptionLists, abbreviated as OL, are AnyLogics version of Java Enums. There are many OptionLists in the LUX model. Some of the more commonly used are: OL_EnergyCarriers OL_AssetFlowCategories OL_EnergyAssetType OL_GridConnectionHeatingType OL_GridNodeType Option lists always have the prefix 'OL'. Entries in option lists are always capitalized, with underscores for spaces. e.g. ELECTRICITY, PETROLEUM_FUEL.","title":"Option Lists"},{"location":"engine/overview/","text":"Engine The engine is the main component of the simulation software. The engine contains the needed classes to input a full description of the energy system, as well as the tools to run simulations. This includes the decision making algorithms that decide the behaviour of agents as well as the data structures to store all the results of a simulation. The main agent of the engine is called the EnergyModel . This agent contains all other agent populations, like all the GridConnections and GridNodes . The EnergyModel is also where all the energy flows of all agents living in the model accumulate. The populations of agents in the engine are filled by the loader . The engine runs two types of simulations: * Live Simulation * RapidRun Simulation The live simulation serves to give direct feedback to user inputs in the interface . The rapidrun simulation is used to compare model results and KPIs between different scenarios.","title":"Overview"},{"location":"engine/overview/#engine","text":"The engine is the main component of the simulation software. The engine contains the needed classes to input a full description of the energy system, as well as the tools to run simulations. This includes the decision making algorithms that decide the behaviour of agents as well as the data structures to store all the results of a simulation. The main agent of the engine is called the EnergyModel . This agent contains all other agent populations, like all the GridConnections and GridNodes . The EnergyModel is also where all the energy flows of all agents living in the model accumulate. The populations of agents in the engine are filled by the loader . The engine runs two types of simulations: * Live Simulation * RapidRun Simulation The live simulation serves to give direct feedback to user inputs in the interface . The rapidrun simulation is used to compare model results and KPIs between different scenarios.","title":"Engine"},{"location":"engine/data_structures/accumulator_maps/","text":"Accumulator Maps Accumulator Maps store a set of accumulators keyed by an enum type. The implementation is class J_AccumulatorMap> . During the simulation the results are stored in these accumulators. Agents loop over their energy carriers, asset flow categories or other option list and the individual accumulators are accessed and updated. The constructor takes one argument: Class\\ enumClass : The enum type that defines the possible keys. Key methods: createEmptyAccumulators(EnumSet selectedFlows, boolean hasTimeSeries, double signalResolution_h, double duration_h) : Fills the map with accumulators for the given subset of enum keys. All accumulators are created with the same parameters. put(E key, ZeroAccumulator acc) : Adds an individual accumulator for a specific key. get(E key) : Retrieves the accumulator for a given key. getClone() : Returns a deep clone of this map, cloning each accumulator. reset() : Resets all accumulators in the map. clear() : Removes all accumulators from the map. keySet() : Returns the set of keys that have accumulators. add(J_AccumulatorMap accumulatorMap) : adds the accumulators of another accumulator map to the accumulators of this map and returns this object. subtract(J_AccumulatorMap accumulatorMap) : subtracts the accumulators of another accumulator map to the accumulators of this map and returns this object. Accumulator maps can be converted to DataSetMaps via getDataSetMap(startTime_h) or getDataSetMap(startTime_h, dataSetSignalResolution_h) . The latter allows downsampling to a coarser signal resolution, given that it is a multiple of the accumulator's resolution.","title":"Accumulator Maps"},{"location":"engine/data_structures/accumulator_maps/#accumulator-maps","text":"Accumulator Maps store a set of accumulators keyed by an enum type. The implementation is class J_AccumulatorMap> . During the simulation the results are stored in these accumulators. Agents loop over their energy carriers, asset flow categories or other option list and the individual accumulators are accessed and updated. The constructor takes one argument: Class\\ enumClass : The enum type that defines the possible keys. Key methods: createEmptyAccumulators(EnumSet selectedFlows, boolean hasTimeSeries, double signalResolution_h, double duration_h) : Fills the map with accumulators for the given subset of enum keys. All accumulators are created with the same parameters. put(E key, ZeroAccumulator acc) : Adds an individual accumulator for a specific key. get(E key) : Retrieves the accumulator for a given key. getClone() : Returns a deep clone of this map, cloning each accumulator. reset() : Resets all accumulators in the map. clear() : Removes all accumulators from the map. keySet() : Returns the set of keys that have accumulators. add(J_AccumulatorMap accumulatorMap) : adds the accumulators of another accumulator map to the accumulators of this map and returns this object. subtract(J_AccumulatorMap accumulatorMap) : subtracts the accumulators of another accumulator map to the accumulators of this map and returns this object. Accumulator maps can be converted to DataSetMaps via getDataSetMap(startTime_h) or getDataSetMap(startTime_h, dataSetSignalResolution_h) . The latter allows downsampling to a coarser signal resolution, given that it is a multiple of the accumulator's resolution.","title":"Accumulator Maps"},{"location":"engine/data_structures/accumulators/","text":"Accumulators Accumulators are a datastructure created to be able to efficiently store data results of rapidrun simulations. The unit of data inside accumulators is always kW. The accumulator has public methods to inquire about kWh totals (integrals), minima/maxima and a method to convert the timeseries to an AnyLogic DataSet (to render charts / graphs). For a data structure to store data with other units see time series There also exist methods to add and subtract accumulators from eachother. The constructor accepts three arguments: boolean hasTimeSeries : When this boolean is set to true the accumulator will store the entire timeseries. When the boolean is set to false the accumulator will only store specific data about the timeseries, such as the minimum, maximum, and total. double signalResolution_h : This parameter specifies the resolution of the timeseries. The timeseries will store a datapoint for each signalResolution_h. This value must be at least the timestep of the energymodel (15 minutes by default) and can be at most the duration_h. It must also be a divisor of duration_h. double duration_h : The total duration of which we are storing data. For an accumulator that stores data for an entire year this would be 8760 hours, for an accumulator that stores data about one week this would be 672 hours. Every timestep the method addStep should be called with the current power in kW. This method then handles the timeseries and signal resolution.","title":"Accumulators"},{"location":"engine/data_structures/accumulators/#accumulators","text":"Accumulators are a datastructure created to be able to efficiently store data results of rapidrun simulations. The unit of data inside accumulators is always kW. The accumulator has public methods to inquire about kWh totals (integrals), minima/maxima and a method to convert the timeseries to an AnyLogic DataSet (to render charts / graphs). For a data structure to store data with other units see time series There also exist methods to add and subtract accumulators from eachother. The constructor accepts three arguments: boolean hasTimeSeries : When this boolean is set to true the accumulator will store the entire timeseries. When the boolean is set to false the accumulator will only store specific data about the timeseries, such as the minimum, maximum, and total. double signalResolution_h : This parameter specifies the resolution of the timeseries. The timeseries will store a datapoint for each signalResolution_h. This value must be at least the timestep of the energymodel (15 minutes by default) and can be at most the duration_h. It must also be a divisor of duration_h. double duration_h : The total duration of which we are storing data. For an accumulator that stores data for an entire year this would be 8760 hours, for an accumulator that stores data about one week this would be 672 hours. Every timestep the method addStep should be called with the current power in kW. This method then handles the timeseries and signal resolution.","title":"Accumulators"},{"location":"engine/data_structures/data_structures/","text":"Data Structures Data structures are organized ways of storing and managing data. We have implemented several different data structures to fit the needs of our model. These include: Accumulators Accumulator Maps DataSet Maps Flows Maps Profile Pointers Profile Forecasters Time Series Value Maps","title":"Overview"},{"location":"engine/data_structures/data_structures/#data-structures","text":"Data structures are organized ways of storing and managing data. We have implemented several different data structures to fit the needs of our model. These include: Accumulators Accumulator Maps DataSet Maps Flows Maps Profile Pointers Profile Forecasters Time Series Value Maps","title":"Data Structures"},{"location":"engine/data_structures/dataset_maps/","text":"DataSet Maps DataSet Maps store a set of AnyLogic DataSets (2D XY data) keyed by an enum type. The implementation is class J_DataSetMap> . DataSet Maps are typically created from accumulator maps via getDataSetMap(startTime_h) , which converts each accumulator's time series to an AnyLogic DataSet for rendering charts and graphs. The constructor accepts one argument: Class\\ enumClass : The enum type that defines the possible keys. Key methods: createEmptyDataSets(EnumSet selectedFlows, int size) : Creates empty DataSets for the given subset of enum keys. put(E key, DataSet ds) : Associates a DataSet with the given key. get(E key) : Retrieves the DataSet for a given key. clear() : Removes all DataSets. keySet() : Returns the set of keys that have associated DataSets.","title":"DataSet Maps"},{"location":"engine/data_structures/dataset_maps/#dataset-maps","text":"DataSet Maps store a set of AnyLogic DataSets (2D XY data) keyed by an enum type. The implementation is class J_DataSetMap> . DataSet Maps are typically created from accumulator maps via getDataSetMap(startTime_h) , which converts each accumulator's time series to an AnyLogic DataSet for rendering charts and graphs. The constructor accepts one argument: Class\\ enumClass : The enum type that defines the possible keys. Key methods: createEmptyDataSets(EnumSet selectedFlows, int size) : Creates empty DataSets for the given subset of enum keys. put(E key, DataSet ds) : Associates a DataSet with the given key. get(E key) : Retrieves the DataSet for a given key. clear() : Removes all DataSets. keySet() : Returns the set of keys that have associated DataSets.","title":"DataSet Maps"},{"location":"engine/data_structures/flows_maps/","text":"Flows Maps Flows Maps are a data structure to store energy flows per energy carrier . The implementation is class J_FlowsMap . This data structure is used throughout the simulation to pass flow values at each timestep. For example, the current balance flows, consumption flows, and production flows are all stored as J_FlowsMap objects. Internally the values are stored in a fixed-size double array indexed by the ordinal of OL_EnergyCarriers . An EnumSet tracks which carriers have been set, providing faster iteration than iterating over all possible carriers. The constructor takes no arguments: Default constructor : Prepares an empty flows map with all energy carrier slots initialized to zero. The following methods are available: get(OL_EnergyCarriers key) : Returns the flow value for the given energy carrier. put(OL_EnergyCarriers key, double value) : Sets the flow value for a carrier. addFlow(OL_EnergyCarriers key, double value) : Adds value to the existing flow for a carrier. addFlows(J_FlowsMap f) : Adds all flows from another flows map. removeFlows(J_FlowsMap f) : Subtracts all flows from another flows map. cloneMap(J_FlowsMap flowMap) : Copies all values from another map. clear() : Resets all values to zero. totalSum() : Returns the sum of all flows. Reduced Flows Map There is also a J_ReducedFlowsMap that extends EnumMap . It overrides get(Object key) to return 0.0 instead of null for unset keys. It provides the same addFlow() and addReducedFlows() convenience methods and is used for aggregating flows from multiple J_FlowsMap objects. For a generic version of this data structure (not restricted to OL_EnergyCarriers ) see value maps .","title":"Flows Maps"},{"location":"engine/data_structures/flows_maps/#flows-maps","text":"Flows Maps are a data structure to store energy flows per energy carrier . The implementation is class J_FlowsMap . This data structure is used throughout the simulation to pass flow values at each timestep. For example, the current balance flows, consumption flows, and production flows are all stored as J_FlowsMap objects. Internally the values are stored in a fixed-size double array indexed by the ordinal of OL_EnergyCarriers . An EnumSet tracks which carriers have been set, providing faster iteration than iterating over all possible carriers. The constructor takes no arguments: Default constructor : Prepares an empty flows map with all energy carrier slots initialized to zero. The following methods are available: get(OL_EnergyCarriers key) : Returns the flow value for the given energy carrier. put(OL_EnergyCarriers key, double value) : Sets the flow value for a carrier. addFlow(OL_EnergyCarriers key, double value) : Adds value to the existing flow for a carrier. addFlows(J_FlowsMap f) : Adds all flows from another flows map. removeFlows(J_FlowsMap f) : Subtracts all flows from another flows map. cloneMap(J_FlowsMap flowMap) : Copies all values from another map. clear() : Resets all values to zero. totalSum() : Returns the sum of all flows.","title":"Flows Maps"},{"location":"engine/data_structures/flows_maps/#reduced-flows-map","text":"There is also a J_ReducedFlowsMap that extends EnumMap . It overrides get(Object key) to return 0.0 instead of null for unset keys. It provides the same addFlow() and addReducedFlows() convenience methods and is used for aggregating flows from multiple J_FlowsMap objects. For a generic version of this data structure (not restricted to OL_EnergyCarriers ) see value maps .","title":"Reduced Flows Map"},{"location":"engine/data_structures/profile_forecasters/","text":"Profile Forecasters Profile Forecasters compute a rolling average forecast over a profile pointer . The implementation is class J_ProfileForecaster . A forecaster takes a profile pointer and computes the average value over a configurable forecast horizon. As the simulation progresses, the forecast window slides forward and the average is updated incrementally. The constructor accepts the following arguments: String forecastName : An optional name for this forecaster. If null, it is automatically generated from the profile pointer name and forecast horizon. J_ProfilePointer profilePointer : The underlying profile to forecast over. double forecastTime_h : The length of the forecast horizon in hours. double currentTime_h : The current simulation time used for the initial forecast calculation. double timeStep_h : The simulation time step, used to determine the number of samples in the forecast window. Key methods: initializeForecast(double currentTime_h) : Computes the initial forecast as the average of all profile values from currentTime_h to currentTime_h + forecastTime_h . updateForecast(double t_h) : Updates the forecast by removing the contribution of the value at t_h and adding the contribution of the value at t_h + forecastTime_h (sliding window). getForecast() : Returns the current forecasted average value. getForecastTime_h() : Returns the length of the forecast horizon. getName() : Returns the name of this forecaster. The sliding window update in updateForecast is efficient: it only needs two profile lookups per timestep rather than recomputing the entire average.","title":"Profile Forecasters"},{"location":"engine/data_structures/profile_forecasters/#profile-forecasters","text":"Profile Forecasters compute a rolling average forecast over a profile pointer . The implementation is class J_ProfileForecaster . A forecaster takes a profile pointer and computes the average value over a configurable forecast horizon. As the simulation progresses, the forecast window slides forward and the average is updated incrementally. The constructor accepts the following arguments: String forecastName : An optional name for this forecaster. If null, it is automatically generated from the profile pointer name and forecast horizon. J_ProfilePointer profilePointer : The underlying profile to forecast over. double forecastTime_h : The length of the forecast horizon in hours. double currentTime_h : The current simulation time used for the initial forecast calculation. double timeStep_h : The simulation time step, used to determine the number of samples in the forecast window. Key methods: initializeForecast(double currentTime_h) : Computes the initial forecast as the average of all profile values from currentTime_h to currentTime_h + forecastTime_h . updateForecast(double t_h) : Updates the forecast by removing the contribution of the value at t_h and adding the contribution of the value at t_h + forecastTime_h (sliding window). getForecast() : Returns the current forecasted average value. getForecastTime_h() : Returns the length of the forecast horizon. getName() : Returns the name of this forecaster. The sliding window update in updateForecast is efficient: it only needs two profile lookups per timestep rather than recomputing the entire average.","title":"Profile Forecasters"},{"location":"engine/data_structures/profile_pointers/","text":"Profile Pointers Profile Pointers provide access to time-series input data, such as weather profiles (temperature, irradiance, wind speed) or market prices. The implementation is class J_ProfilePointer . Unlike Accumulators and Time Series which store simulation results , profile pointers read pre-defined input profiles. The profile data is stored as a double[] array with a fixed timestep. The constructor accepts the following arguments: String name : A descriptive name for this profile (e.g. \"ground_temperature\", \"day_ahead_electricity_price\"). double[] profile : The array of data values. double dataTimeStep_h : The time step between consecutive values in the profile array. double dataStartTime_h : The start time of the first profile entry, relative to 00:00 on January 1st of the simulation year. OL_ProfileUnits profileUnits : The physical unit of the profile values. Key methods: getCurrentValue() : Returns the most recently updated value. getValue(double time_h) : Returns the profile value at the given simulation time. Supports profile looping: when enableProfileLooping is true (default), indices beyond the array length wrap around using modular arithmetic. updateValue(double t_h) : Calls getValue(t_h) and stores the result internally. getAllValues() : Returns a clone of the full profile array. getDataTimeStep_h() : Returns the time step of the profile data. The updateValue / getCurrentValue pattern is used each timestep, called by the EnergyModel for all profile pointers during the simulation to avoid repeated index calculations. For forecasting over a profile, see profile forecasters .","title":"Profile Pointers"},{"location":"engine/data_structures/profile_pointers/#profile-pointers","text":"Profile Pointers provide access to time-series input data, such as weather profiles (temperature, irradiance, wind speed) or market prices. The implementation is class J_ProfilePointer . Unlike Accumulators and Time Series which store simulation results , profile pointers read pre-defined input profiles. The profile data is stored as a double[] array with a fixed timestep. The constructor accepts the following arguments: String name : A descriptive name for this profile (e.g. \"ground_temperature\", \"day_ahead_electricity_price\"). double[] profile : The array of data values. double dataTimeStep_h : The time step between consecutive values in the profile array. double dataStartTime_h : The start time of the first profile entry, relative to 00:00 on January 1st of the simulation year. OL_ProfileUnits profileUnits : The physical unit of the profile values. Key methods: getCurrentValue() : Returns the most recently updated value. getValue(double time_h) : Returns the profile value at the given simulation time. Supports profile looping: when enableProfileLooping is true (default), indices beyond the array length wrap around using modular arithmetic. updateValue(double t_h) : Calls getValue(t_h) and stores the result internally. getAllValues() : Returns a clone of the full profile array. getDataTimeStep_h() : Returns the time step of the profile data. The updateValue / getCurrentValue pattern is used each timestep, called by the EnergyModel for all profile pointers during the simulation to avoid repeated index calculations. For forecasting over a profile, see profile forecasters .","title":"Profile Pointers"},{"location":"engine/data_structures/time_series/","text":"Time Series The class ZeroTimeSeries is almost completely analogous to the Accumulator except that it does not require the entries to have the unit kW (any unit can be used). It is different in the following ways: The time series class always stores the full time series as a double[] array, whereas this is optional for the accumulator. The time series stores only one value per signal resolution entry (no averaging of sub-steps when resolution differs from the simulation timestep \u2014 it uses a sample weight instead). There is no 'map' variant of the time series object to conveniently store multiple series for different energy carriers or other option lists, as this has not been needed. The time series provides getSum() , getSumPos() , and getSumNeg() methods (raw sums of the time series values), whereas the accumulator provides integrals in kWh. The constructor accepts two arguments: double signalResolution_h : The resolution of the time series. Must be at least the simulation timestep. double duration_h : The total duration for which data is stored. Key methods: addStep(double value) : Adds a data point for the current time step. getSum() / getSumPos() / getSumNeg() : Returns the sum, positive sum, or negative sum of all values. getTimeSeries() : Returns the underlying double[] array. getMax() / getMin() : Returns the maximum/minimum value. getDataSet(double startTime_h) : Converts the time series to an AnyLogic DataSet for charting. add(ZeroTimeSeries zts) / subtract(ZeroTimeSeries zts) : Element-wise addition/subtraction of time series. The time series object is used to store simulation results. Compare this to the profile pointer , which also stores a series of data points, but these are input data like weather data or market prices.","title":"Time Series"},{"location":"engine/data_structures/time_series/#time-series","text":"The class ZeroTimeSeries is almost completely analogous to the Accumulator except that it does not require the entries to have the unit kW (any unit can be used). It is different in the following ways: The time series class always stores the full time series as a double[] array, whereas this is optional for the accumulator. The time series stores only one value per signal resolution entry (no averaging of sub-steps when resolution differs from the simulation timestep \u2014 it uses a sample weight instead). There is no 'map' variant of the time series object to conveniently store multiple series for different energy carriers or other option lists, as this has not been needed. The time series provides getSum() , getSumPos() , and getSumNeg() methods (raw sums of the time series values), whereas the accumulator provides integrals in kWh. The constructor accepts two arguments: double signalResolution_h : The resolution of the time series. Must be at least the simulation timestep. double duration_h : The total duration for which data is stored. Key methods: addStep(double value) : Adds a data point for the current time step. getSum() / getSumPos() / getSumNeg() : Returns the sum, positive sum, or negative sum of all values. getTimeSeries() : Returns the underlying double[] array. getMax() / getMin() : Returns the maximum/minimum value. getDataSet(double startTime_h) : Converts the time series to an AnyLogic DataSet for charting. add(ZeroTimeSeries zts) / subtract(ZeroTimeSeries zts) : Element-wise addition/subtraction of time series. The time series object is used to store simulation results. Compare this to the profile pointer , which also stores a series of data points, but these are input data like weather data or market prices.","title":"Time Series"},{"location":"engine/data_structures/value_maps/","text":"Value Maps Value Maps are a generic data structure for storing a double value for each key in an enum set. The implementation is class J_ValueMap> . Internally the values are stored in a flat array indexed by the enum ordinal. An EnumSet tracks which keys have been set. This makes value maps more memory-efficient and faster than using a HashMap or EnumMap . The constructor accepts the enum Class : Class\\ enumClass : The enum type that defines the possible keys. All enum constants are pre-allocated in the internal array. The following methods are available: get(E key) : Returns the current value for the given key. put(E key, double value) : Sets the value for the given key. addFlow(E key, double value) : Adds value to the existing value for the key. addFlows(J_ValueMap f) : Adds all values from another value map. removeFlows(J_ValueMap f) : Subtracts all values from another value map. cloneMap(J_ValueMap flowMap) : Copies all values from another map. clear() : Resets all values to zero. totalSum() : Returns the sum of all values. Value Maps are similar to Flows Maps , but are generic over any enum type, whereas flows maps are specifically for OL_EnergyCarriers .","title":"Value Maps"},{"location":"engine/data_structures/value_maps/#value-maps","text":"Value Maps are a generic data structure for storing a double value for each key in an enum set. The implementation is class J_ValueMap> . Internally the values are stored in a flat array indexed by the enum ordinal. An EnumSet tracks which keys have been set. This makes value maps more memory-efficient and faster than using a HashMap or EnumMap . The constructor accepts the enum Class : Class\\ enumClass : The enum type that defines the possible keys. All enum constants are pre-allocated in the internal array. The following methods are available: get(E key) : Returns the current value for the given key. put(E key, double value) : Sets the value for the given key. addFlow(E key, double value) : Adds value to the existing value for the key. addFlows(J_ValueMap f) : Adds all values from another value map. removeFlows(J_ValueMap f) : Subtracts all values from another value map. cloneMap(J_ValueMap flowMap) : Copies all values from another map. clear() : Resets all values to zero. totalSum() : Returns the sum of all values. Value Maps are similar to Flows Maps , but are generic over any enum type, whereas flows maps are specifically for OL_EnergyCarriers .","title":"Value Maps"},{"location":"interface/overview/","text":"Interface","title":"Overview"},{"location":"interface/overview/#interface","text":"","title":"Interface"},{"location":"loader/overview/","text":"Loader","title":"Overview"},{"location":"loader/overview/#loader","text":"","title":"Loader"},{"location":"loader/lombok/lombok/","text":"Lombok in AnyLogic Installation Project Lombok can do code generation to improve the experience of working with Java code. It can add common patterns like builder classes, value classes, null checks, and getters. To use it in AnyLogic: 1. Download lombok.jar and place it in the AnyLogic directory, for example C:\\Program Files\\AnyLogic 8.9 Personal Learning Edition\\lombok.jar 2. Add the line below to AnyLogic.ini in the same directory. To do this in Windows, run notepad as Administrator and then navigate to the file via \"File\" > \"Open\". -javaagent:./lombok.jar AnyLogic.ini should look like this: -vmargs -Xmx4096M -Djava.util.Arrays.useLegacyMergeSort=true --add-modules=ALL-SYSTEM -Dorg.eclipse.e4.ui.css.theme.disableOSDarkThemeInherit=true -Dsun.java2d.ddscale=true -Dsun.java2d.translaccel=true --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED -javaagent:./lombok.jar 3. Add lombok.jar to your project's dependencies. 4. If you have a custom launch script ( .bat , .sh ) it may not find lombok.jar . To fix it you can place the launch script in the AnyLogic directory. set CLIENT_ID=xxx set CLIENT_SECRET=xxx Anylogic.exe 5. You can now use the annotations in your project. Using @Builder for Agents You may want to use Lombok outside of plain Java code. To create a builder class for an Agent, add these annotations to the bottom of the imports section of that Agent: @lombok.AllArgsConstructor @lombok.Builder Use it like so:","title":"Lombok"},{"location":"loader/lombok/lombok/#lombok-in-anylogic","text":"","title":"Lombok in AnyLogic"},{"location":"loader/lombok/lombok/#installation","text":"Project Lombok can do code generation to improve the experience of working with Java code. It can add common patterns like builder classes, value classes, null checks, and getters. To use it in AnyLogic: 1. Download lombok.jar and place it in the AnyLogic directory, for example C:\\Program Files\\AnyLogic 8.9 Personal Learning Edition\\lombok.jar 2. Add the line below to AnyLogic.ini in the same directory. To do this in Windows, run notepad as Administrator and then navigate to the file via \"File\" > \"Open\". -javaagent:./lombok.jar AnyLogic.ini should look like this: -vmargs -Xmx4096M -Djava.util.Arrays.useLegacyMergeSort=true --add-modules=ALL-SYSTEM -Dorg.eclipse.e4.ui.css.theme.disableOSDarkThemeInherit=true -Dsun.java2d.ddscale=true -Dsun.java2d.translaccel=true --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED -javaagent:./lombok.jar 3. Add lombok.jar to your project's dependencies. 4. If you have a custom launch script ( .bat , .sh ) it may not find lombok.jar . To fix it you can place the launch script in the AnyLogic directory. set CLIENT_ID=xxx set CLIENT_SECRET=xxx Anylogic.exe 5. You can now use the annotations in your project.","title":"Installation"},{"location":"loader/lombok/lombok/#using-builder-for-agents","text":"You may want to use Lombok outside of plain Java code. To create a builder class for an Agent, add these annotations to the bottom of the imports section of that Agent: @lombok.AllArgsConstructor @lombok.Builder Use it like so:","title":"Using @Builder for Agents"},{"location":"resultsUI/overview/","text":"Results UI","title":"Overview"},{"location":"resultsUI/overview/#results-ui","text":"","title":"Results UI"}]}
\ No newline at end of file
diff --git a/site/sitemap.xml.gz b/site/sitemap.xml.gz
index cf06816..2c6ac7a 100644
Binary files a/site/sitemap.xml.gz and b/site/sitemap.xml.gz differ