Skip to content

Digitalized-Energy-Systems/MangoEnergyEnvironments.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lifecycle MIT License

Mango Energy Environments

Energy-domain environments for Mango.jl. Each environment is an EnvironmentBehavior that wraps a physical simulation and exposes observers, actions, and events so that Mango agents can perceive and influence it.

Concept

Environments are implemented against the Mango.jl world environment API as EnvironmentBehavior subtypes. The behavior is attached to a World at construction time and drives the underlying physical simulation. Agents are connected to specific elements of the simulation via Mango.install, which registers typed observers and actions on the agent.

Standard Environment Contract

Every environment in this package follows the same structure:

Concern API
Physical simulation Updated inside Mango.on_step / Mango.initialize
Connect an agent Mango.install(behavior, agent; id, type)
Read state Named observers installed on the agent
Change state Named actions installed on the agent
React to changes Global or agent events emitted by the behavior
Schedule disturbances Behavior-specific scheduling functions

Environment: Multi-Energy Restoration

Behavior: RestorationEnvironmentBehavior Physical system: Coupled multi-energy network (electricity, gas, heat) via MONEE Prerequisites: monee installed in the PyCall Python environment (pip install monee)

Concept

The behavior wraps a MONEE Python network object and re-runs energy flow analysis whenever the network state changes. Failures can be scheduled to deactivate branches or nodes at a given simulation time, which triggers global events that all agents receive.

Agents API

Connect an agent to a network element via:

Mango.install(behavior, agent; id=<element_id>, type=:<node|branch|child>)
type Observer (unnamed) Actions
:node node.model.values dict :regulate(factor) — if node model supports it
:branch branch.model.values dict :switch() — toggle on/off; :regulate(factor) — if supported
:child merged node.model.values + child.model.values dict :regulate(factor)

Events

Event Scope Emitted when
BranchFailureEvent(branch_id) Global A branch is deactivated by a scheduled failure
NodeFailureEvent(node_id) Global A node is deactivated by a scheduled failure
CustomFailureEvent(custom_id) Global A custom failure function fires

Key Functions

Function Description
schedule_failure(behavior, world, clock, failure) Schedule a Failure event
topology_based_on_grid(net, topology, world) Build a Mango topology mirroring the physical grid
topology_based_on_grid_groups(net, topology, world) Build a topology grouped by connected component
apply_failures(net, failures) Apply a list of failures directly to a network (no events)
fetch_example_net() / fetch_cigre_net() Load example MONEE networks

Example

using MangoEnergyEnvironments
using Mango
using Dates

monee_net = fetch_example_net()
behavior = RestorationEnvironmentBehavior(net=monee_net)
world = create_world(DateTime(2024, 08, 1, 0, 0, 0), behavior=behavior,
        communication_sim=SimpleCommunicationSimulation(default_delay_s=0.02))

# One agent per network node
for node in monee_net.nodes
    add_agent_composed_of(world, BranchFailureHandler(); suggested_aid=node.tid)
end

# Topology mirrors physical grid connectivity
topology_grid = create_topology((topology) -> topology_based_on_grid(monee_net, topology, world))

# React to branch failures: remember and propagate to neighbors
behavior_in(world, on_global_event=BranchFailureEvent, role_types=BranchFailureHandler) do role, _
    role.counter += 1
    send_messages(role, "Failure attention!", topology_neighbors(role))
end
behavior_in(world, on_message=String, role_types=BranchFailureHandler) do role, msg, _
    role.msg_counter += 1
end

# Schedule a branch failure at t=2s
failures = [Failure(delay_s=2, branch_ids=[(monee_net.branches[3].id, monee_net.branches[3].nid)])]

activate(world) do
    for failure in failures
        schedule_failure(behavior, world, clock(world), failure)
    end
    discrete_step_until(world, 10)
end

Environment: Power Systems Scheduling

Behavior: PowerSystemsBehavior Physical system: AC power network via PowerSystems.jl Prerequisites: PowerSystems.jl, PowerSimulations.jl; HiGHS (for solve_central)

Concept

The behavior reads timeseries data from a PowerSystems.System at initialization and schedules all future value changes as simulation tasks. Each change notifies the associated agent via a PowerUpdateInfo event. Agents can observe component properties and, for controllable devices, regulate active power output.

Agents API

Connect an agent to a system component via:

Mango.install(behavior, agent; id=<component_uuid>, type=:component)

The type argument is unused; the component type is inferred automatically from id.

Observer Returns
:statics All static fields of the component as a Dict
:max_active_power Current maximum active power (updated by timeseries)
:active_power Current dispatch setpoint
Action Available for Description
:regulate(active_power) ThermalStandard, RenewableDispatch, EnergyReservoirStorage Set active power output

Events

Event Scope Emitted when
PowerUpdateInfo Agent A timeseries step updates the component's value

Key Functions

Function Description
calculate_initial_time(behavior) Returns the earliest timestamp across all component timeseries
get_possible_components(behavior) Returns all components matching relevant_components
get_components_by_type(behavior, types) Filter components by a list of types
solve_central(behavior) Solve a 24-hour economic dispatch centrally (HiGHS)

Example

using MangoEnergyEnvironments
using Mango
using PowerSystems
using PowerSystemCaseBuilder
using Dates

sys = build_system(PSITestSystems, "c_sys5_bat")
behavior = PowerSystemsBehavior(system=sys, relevant_components=[PowerLoad, ThermalStandard])

initial_time = calculate_initial_time(behavior)
world = create_world(initial_time, behavior=behavior)

# One agent per relevant component
for component in get_possible_components(behavior)
    agent = add_agent_composed_of(world, LoadMonitor(); suggested_aid=string(get_uuid(component)))
    Mango.install(behavior, agent; id=get_uuid(component), type=:component)
end

# React to timeseries updates
behavior_in(world, on_agent_event=PowerUpdateInfo, role_types=LoadMonitor) do role, _
    p_max = observe(role, :max_active_power)
    # ... agent logic
end

activate(world) do
    discrete_step_until(world, Hour(48))
end

About

This package contains environments for Mango.jl from the energy domain.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors