varshu23's picture
Clean commit without images
5a22808
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
"""
Data models for the Thermal Grid Rl Agent Environment.
The agent interacts with a high-dimensional datacenter + power-grid environment.
It observes thermal state, IT load, and external grid signals, then controls:
A. Cooling (continuous) — CRAC setpoints, fan speeds (VFD), chiller stacking
B. Load distribution (discrete/structural) — geographical load balancing (GLB)
and batch-job scheduling
"""
from openenv.core.env_server.types import Action, Observation
from pydantic import Field
# ---------------------------------------------------------------------------
# Action
# ---------------------------------------------------------------------------
class ThermalGridRlAgentAction(Action):
"""
Control action for the Thermal Grid RL Agent.
Two distinct levers that interact: redistributing load changes the thermal
profile, which in turn requires adjustments to cooling.
A. Cooling Control (Continuous)
--------------------------------
crac_setpoint_c : CRAC/CRAH supply-air temperature setpoint (°C).
fan_speeds_pct : Per-rack Variable Frequency Drive fan speed 0–100 %.
Power scales as Speed³ (Affinity Laws), so small
reductions yield large savings.
num_active_chillers: How many chiller units to run. A chiller at 20 %
load is far less efficient than one at 80 % load.
B. Load Distribution (Discrete / Structural)
---------------------------------------------
region_traffic_weights : Fraction of incoming user traffic routed to each
region (must sum to 1.0). Enables GLB — shift
traffic away from hot/expensive regions.
batch_job_schedule : Per-batch-job flag — 1 = run now, 0 = defer to
off-peak. Enables temporal load shifting.
workload_matrix : Per-server utilisation after placement (0–1),
shape [num_racks][servers_per_rack].
power_caps_w : Per-server power cap in Watts.
"""
# ---- A. Cooling (continuous) -----------------------------------------
crac_setpoint_c: float = Field(
default=18.0,
description="CRAC/CRAH supply-air temperature setpoint in °C (12.0–27.0)",
)
fan_speeds_pct: list[float] = Field(
default_factory=lambda: [60.0] * 10,
description=(
"Per-rack fan speed (0–100 %). Power ∝ Speed³ (Affinity Laws). "
"One value per rack."
),
)
num_active_chillers: int = Field(
default=2,
description=(
"Number of chiller units to activate (1–max_chillers). "
"Fewer chillers at higher load is more efficient than many at low load."
),
)
# ---- B. Load distribution (discrete / structural) --------------------
region_traffic_weights: list[float] = Field(
default_factory=lambda: [1.0],
description=(
"Fraction of live user traffic routed to each region (sums to 1.0). "
"Geographical Load Balancing (GLB) lever."
),
)
batch_job_schedule: list[int] = Field(
default_factory=list,
description=(
"Per-batch-job scheduling flag: 1 = run this step, 0 = defer to "
"off-peak. Enables temporal load shifting."
),
)
workload_matrix: list[list[float]] = Field(
default_factory=lambda: [[0.5] * 8] * 10,
description=(
"Per-server utilisation after placement decisions (0–1). "
"Shape [num_racks][servers_per_rack]."
),
)
power_caps_w: list[list[float]] = Field(
default_factory=lambda: [[300.0] * 8] * 10,
description="Per-server power cap in Watts. Shape [num_racks][servers_per_rack].",
)
metadata: dict = Field(default_factory=dict, description="Metadata dictionary for tracking action provenance")
# ---------------------------------------------------------------------------
# Observation
# ---------------------------------------------------------------------------
class ThermalGridRlAgentObservation(Observation):
"""
Observation returned by the Thermal Grid RL Agent environment.
Groups into four sections mirroring the environment's key components:
1. Thermal state — rack inlet/CPU temps, thermal mass lag indicator
2. IT load — per-rack power, utilisation, live vs batch split
3. Cooling state — PUE, CRAC/chiller status, fan speeds
4. External grid — energy price, carbon intensity, demand-response flag
"""
step_summary: str = Field(default="", description="Step summary string")
# ---- 1. Thermal state ------------------------------------------------
inlet_temps_c: list[float] = Field(
default_factory=list,
description="Per-rack cold-aisle inlet temperature in °C",
)
mean_cpu_temps_c: list[float] = Field(
default_factory=list,
description="Per-rack mean CPU junction temperature in °C",
)
max_cpu_temps_c: list[float] = Field(
default_factory=list,
description="Per-rack maximum CPU junction temperature in °C",
)
max_gpu_temps_c: list[float] = Field(
default_factory=list,
description="Per-rack maximum GPU junction temperature in °C",
)
thermal_mass_lag_c_per_min: float = Field(
default=0.0,
description=(
"Estimated rate of temperature change (°C/min) due to thermal mass. "
"Positive = room heating up; negative = cooling down. "
"Enables predictive rather than purely reactive control."
),
)
# ---- 2. IT load ------------------------------------------------------
rack_powers_w: list[float] = Field(
default_factory=list,
description="Per-rack total IT power draw in Watts",
)
rack_utilisation: list[float] = Field(
default_factory=list,
description="Per-rack mean server utilisation (0–1)",
)
live_traffic_load_w: float = Field(
default=0.0,
description="Power attributable to live user-facing traffic (Watts)",
)
deferred_batch_load_w: float = Field(
default=0.0,
description="Power attributable to batch jobs running this step (Watts)",
)
pending_batch_jobs: int = Field(
default=0,
description="Number of batch jobs currently queued / deferred",
)
# ---- 3. Cooling state ------------------------------------------------
pue: float = Field(
default=0.0,
description="Power Usage Effectiveness = total facility power / IT power",
)
total_it_power_w: float = Field(default=0.0, description="Total IT power draw in Watts")
# ---- Episode metadata ------------------------------------------------
done: bool = Field(default=False, description="1 if the episode has ended")
reward: float = Field(default=0.0, description="Reward from the environment")
safety_override_triggered: bool = Field(
default=False,
description="True if the Hard Safety Layer overrode agent actions to prevent damage",
)
metadata: dict = Field(default_factory=dict, description="Metadata dictionary")
total_facility_power_w: float = Field(default=0.0, description="Total facility power in Watts")
crac_power_w: float = Field(default=0.0, description="CRAC/CRAH unit power draw in Watts")
chiller_power_w: float = Field(default=0.0, description="Active chiller unit power draw in Watts")
num_active_chillers: int = Field(
default=0,
description="Number of chiller units currently running",
)
chiller_load_pct: float = Field(
default=0.0,
description=(
"Mean load fraction across active chillers (0–100 %). "
"Low values (< 40 %) indicate inefficient part-load operation."
),
)
crac_supply_temp_c: float = Field(
default=0.0,
description="Current CRAC supply-air temperature setpoint in °C",
)
avg_fan_speed_pct: float = Field(
default=0.0,
description="Average VFD fan speed across all racks (0–100 %)",
)
# ---- 4. External grid ------------------------------------------------
ambient_temp_c: float = Field(
default=25.0,
description="Current ambient air temperature in °C. Affects chiller and CRAC efficiency.",
)
energy_price_per_kwh: float = Field(
default=0.0,
description=(
"Current electricity price ($/kWh). Changes hourly (TOU) or every "
"5 minutes (Real-Time Pricing). Key signal for temporal load shifting."
),
)
grid_carbon_intensity_g_per_kwh: float = Field(
default=0.0,
description=(
"Grid carbon intensity (gCO₂/kWh). Low during solar/wind peaks, "
"high during fossil-fuel peaks."
),
)
demand_response_signal: int = Field(
default=0,
description=(
"Binary grid demand-response request: 1 = grid requests load shed "
"to prevent instability, 0 = normal operation."
),
)
off_peak_window: int = Field(
default=0,
description=(
"1 if current time falls within off-peak pricing window "
"(e.g. 02:00–05:00), 0 otherwise. Used for batch job scheduling."
),
)