diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 35a0a2e49..9743b9340 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - id: yamlfix # Exclude YAML files that are used as inputs for testing or examples, or ones for desired schedule in HOPP as they # expect misformatted YAML files. - exclude: ^(h2integrate/core/test/inputs/.*|examples/11_hybrid_energy_plant/tech_inputs/desired_schedules/.*|examples/33_peak_load_management/demand_profiles/.*)$ + exclude: ^(h2integrate/core/test/inputs/.*|examples/11_hybrid_energy_plant/tech_inputs/desired_schedules/.*|examples/33_peak_load_management/demand_profiles/.*|examples/34_plm_optimized_dispatch/demand_profiles/.*)$ - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.8.1 diff --git a/docs/control/figures/plm_optimized_dispatch.png b/docs/control/figures/plm_optimized_dispatch.png new file mode 100644 index 000000000..fd036f846 Binary files /dev/null and b/docs/control/figures/plm_optimized_dispatch.png differ diff --git a/docs/control/pyomo_controllers.md b/docs/control/pyomo_controllers.md index 4aa632a8e..09f93e5af 100644 --- a/docs/control/pyomo_controllers.md +++ b/docs/control/pyomo_controllers.md @@ -110,3 +110,124 @@ tech_to_dispatch_connections: [ ["battery", "battery"], ] ``` + +# Optimized Demand Response Controller + +This controller optimizes the dispatch of a Battery Energy Storage System (BESS) based on a pre-defined supervisory signal. This signal could be the Locational Marginal Price (LMP), a demand profile, or an $LMP\times demand$ product depending on the application. The objective is to maximize incentive payments to the battery, subject to constraints on the maximum number of dispatch events per month and on the battery state of charge. + +The controller works at any simulation timestep resolution (`dt`). All time-based parameters ( `event_duration`, `min_peak_separation`) are specified in physical time units (hours, minutes, etc.) and are internally converted to timesteps using `dt`. + +## Definitions + +**Given:** +- $\lambda_t$ := `supervisory_signal`: price, demand, or price $\times$ demand time series at timestep $t$ +- $\Delta t$ := simulation timestep duration (hours), derived from `dt` in the plant config +- $\mathcal{W}$ := `peak_window`: set of timesteps eligible for dispatch (e.g., 12:00-20:00 each day) +- $\lambda_*$ := signal threshold = `signal_threshold_percentile`-th percentile of $\lambda_t$ over $\mathcal{W}$ +- `min_peak_separation` := minimum required time between two eligible peaks, expressed as a ``{units, val}`` dict. When set, only the first eligible peak is chosen. +- $\mathcal{E}$ := eligible peak timesteps: $\{t \in \mathcal{W} : \lambda_t \geq \lambda_*\}$, respecting `min_peak_separation` +- `event_duration` := total duration of one discharge event, expressed as a ``{units, val}`` dict (e.g. ``{units: h, val: 4}`` for a 4-hour event) +- $\mathcal{D}$ := dispatch window: $\pm$`event_duration`/2 neighbourhoods around each peak in $\mathcal{E}$ (equals $\mathcal{E}$ when `event_duration` is `null`) +- $\gamma$ := incentive revenue per kWh discharged (\$/kWh). Specified directly via `performance_incentive`, or derived from `performance_incentive_per_event` (\$/event) as $\gamma = \gamma_{\text{event}} / (\tau \cdot \Delta t \cdot P_{\max})$ +- $P_{\max}$ := `max_charge_rate` (kW): maximum charge and discharge rate +- $E_{\max} :=$ `max_capacity` $\times$ (`max_soc_fraction` $-$ `min_soc_fraction`): usable energy capacity (kWh) +- $\eta_c$ := `charge_efficiency`, $\quad \eta_d$ := `discharge_efficiency` +- $\text{SoC}_{\max}$ := `max_soc_fraction`, $\quad \text{SoC}_{\min}$ := `min_soc_fraction` +- `n_control_window_hours` := rolling horizon length in hours; converted to $T =$ `n_control_window_hours` / $\Delta t$ timesteps +- $\mathcal{T} := \{0, 1, \ldots, T-1\}$: timesteps in the current rolling window +- $\mathcal{M}_m$ := set of timesteps in month $m$, for $m = 1, \ldots, 12$ +- $N_{\max}$ := `n_max_events`: maximum number of discharge events per calendar month +- $\tau$ := `steps_per_event` : number of timesteps per event (1 when `event_duration` is `null`) +- $B_m$ := remaining event budget for month $m$ = $N_{\max}$ minus events already dispatched in prior windows + +## Dispatch Window Construction + +Before the MILP is solved, the dispatch window $\mathcal{D}$ is built in two steps: + +**Step 1 : Peak selection:** Within $\mathcal{W}$, timesteps at or above the `signal_threshold_percentile` of $\lambda_t$ are marked eligible: $\mathcal{E} = \{t \in \mathcal{W} : \lambda_t \geq \lambda_*\}$. If `min_peak_separation` is set, only the first peak is chosen. + +**Step 2 : Event window expansion:** If `event_duration` is specified, each peak in $\mathcal{E}$ is expanded by $\pm$ `event_duration`/2 timesteps to form $\mathcal{D}$. If `event_duration` is `null`, $\mathcal{D} = \mathcal{E}$. + +## Decision Variables + + +- $u_t \in \{0, 1\}$ := discharge binary: 1 if a discharge event is active at timestep $t$; used for event counting and window feasibility constraints only +- $v_t \in \{0, 1\}$ := charge binary: 1 if a charge event is active at timestep $t$ +- $p_{d,t} \in [0,\, P_{\max}]$ := discharge power (kW) actually dispatched at timestep $t$ +- $p_{c,t} \in [0,\, P_{\max}]$ := charge power (kW) actually consumed at timestep $t$ +- $\text{SoC}_t \in [\text{SoC}_{\min},\, \text{SoC}_{\max}]$ := state of charge (fraction) at timestep $t$ + +## Optimization Problem + +This optimization is executed for each rolling window. At each window boundary the terminal SoC is carried forward as the initial condition for the next window. + +### Objective + +Maximize total incentive revenue over the window: + +$$ +\max_{u_t, v_t,p_{d,t}, p_{c,t}} \quad \gamma \cdot \Delta t \sum_{t \in \mathcal{T}} p_{d,t} +$$ + +The factor $\Delta t$ converts power (kW) to energy (kWh), so the objective is correctly scaled at any timestep resolution. + +### Constraints + +- Dispatch only within the event window $\mathcal{D}$: + +$$ +u_t = 0 \qquad \forall\, t \notin \mathcal{D} +$$ + +- Maximum $N_{\max}$ discharge events per month. Because `event_duration` fixes each event to exactly $\tau$ timesteps, the event cap translates directly into a timestep cap: + +$$ +\sum_{t \in \mathcal{M}_m \cap \mathcal{T}} u_t \leq B_m \cdot \tau \qquad \forall\, m +$$ + +After each window is solved, events are counted via rising-edge detection (a new event begins whenever $u_t = 1$ and $u_{t-1} = 0$) and $B_m$ is decremented accordingly for subsequent windows. + +- Power is zero when the binary is 0, and at most $P_{\max}$ when it is 1: + +$$ +p_{d,t} \leq P_{\max} \cdot u_t \qquad \forall\, t \in \mathcal{T} +$$ + +$$ +p_{c,t} \leq P_{\max} \cdot v_t \qquad \forall\, t \in \mathcal{T} +$$ + +- SoC evolution with continuous charge and discharge power: + +$$ +\text{SoC}_{t} = \text{SoC}_{t-1} + \frac{\eta_c \cdot p_{c,t} \cdot \Delta t}{E_{\max}} - \frac{p_{d,t} \cdot \Delta t}{\eta_d \cdot E_{\max}} \qquad \forall\, t \in \mathcal{T},\, t > 0 +$$ + +- SoC bounds: + +$$ +\text{SoC}_{\min} \leq \text{SoC}_t \leq \text{SoC}_{\max} \qquad \forall\, t \in \mathcal{T} +$$ + +- No simultaneous charge and discharge: + +$$ +u_t + v_t \leq 1 \qquad \forall\, t \in \mathcal{T} +$$ + +- No charging during the dispatch window (battery reserved for discharge): + +$$ +v_t = 0 \qquad \forall\, t \in \mathcal{D} +$$ + +- Variable domains: + +$$ +u_t \in \{0, 1\}, \quad v_t \in \{0, 1\}, \quad p_{d,t},\, p_{c,t} \in [0,\, P_{\max}], \quad \text{SoC}_t \in [\text{SoC}_{\min},\, \text{SoC}_{\max}] \qquad \forall\, t +$$ + + +Example 34 performs the optimization with a synthetic LMP signal. The look-ahead horizon (`n_control_window_hours`) controls how many hours are optimized at once. Larger values improve solution quality but increase solve time. See the figure below for results. + +![](./figures/plm_optimized_dispatch.png) diff --git a/docs/user_guide/model_overview.md b/docs/user_guide/model_overview.md index 6b8d6344f..871389859 100644 --- a/docs/user_guide/model_overview.md +++ b/docs/user_guide/model_overview.md @@ -289,6 +289,7 @@ Below summarizes the available performance, cost, and financial models for each - `'DemandOpenLoopStorageController'`: open-loop control; manages resource flow based on demand and storage constraints - `'HeuristicLoadFollowingStorageController'`: open-loop control that works on a time window basis to set dispatch commands; uses Pyomo - `'PeakLoadManagementHeuristicOpenLoopStorageController'`: open-loop control that reduces peaks rather than trying to meet a load + - `'PeakLoadManagementOptimizedStorageController'`: optimized controller for demand response that works on a time window basis. - Optimized Dispatch: - `'OptimizedDispatchStorageController'`: optimization-based dispatch using Pyomo diff --git a/examples/34_plm_optimized_dispatch/34_plm_optimized_dispatch.yaml b/examples/34_plm_optimized_dispatch/34_plm_optimized_dispatch.yaml new file mode 100644 index 000000000..6f4c89466 --- /dev/null +++ b/examples/34_plm_optimized_dispatch/34_plm_optimized_dispatch.yaml @@ -0,0 +1,5 @@ +name: H2Integrate_config +system_summary: PLM MILP-optimized battery dispatch +driver_config: driver_config.yaml +technology_config: tech_config.yaml +plant_config: plant_config.yaml diff --git a/examples/34_plm_optimized_dispatch/demand_profiles/supervisory_signal.yaml b/examples/34_plm_optimized_dispatch/demand_profiles/supervisory_signal.yaml new file mode 100644 index 000000000..ed3860f5b --- /dev/null +++ b/examples/34_plm_optimized_dispatch/demand_profiles/supervisory_signal.yaml @@ -0,0 +1,8760 @@ +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 121.0501 +- 82.3572 +- 104.0367 +- 89.455 +- 103.9503 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 122.5359 +- 83.9824 +- 142.5416 +- 78.9059 +- 78.5578 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 83.4137 +- 79.0599 +- 85.0666 +- 85.3182 +- 79.7008 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 82.8949 +- 89.15 +- 78.6225 +- 83.3834 +- 101.5483 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 81.5338 +- 71.4758 +- 74.2712 +- 74.3409 +- 69.6864 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 8.0 +- 28.0 +- 28.0 +- 28.0 +- 28.0 +- 71.5507 +- 114.5877 +- 68.5757 +- 84.7005 +- 69.4464 +- 23.0 +- 23.0 +- 23.0 +- 8.0 +- 8.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 18.0 +- 38.0 +- 38.0 +- 38.0 +- 38.0 +- 79.3612 +- 99.056 +- 90.6929 +- 114.607 +- 93.6671 +- 33.0 +- 33.0 +- 33.0 +- 18.0 +- 18.0 diff --git a/examples/34_plm_optimized_dispatch/driver_config.yaml b/examples/34_plm_optimized_dispatch/driver_config.yaml new file mode 100644 index 000000000..c6e002d88 --- /dev/null +++ b/examples/34_plm_optimized_dispatch/driver_config.yaml @@ -0,0 +1,5 @@ +name: driver_config +description: Driver configuration for Peak Load Management MILP-optimized battery dispatch example +general: + folder_output: outputs + create_om_reports: false diff --git a/examples/34_plm_optimized_dispatch/plant_config.yaml b/examples/34_plm_optimized_dispatch/plant_config.yaml new file mode 100644 index 000000000..56838464d --- /dev/null +++ b/examples/34_plm_optimized_dispatch/plant_config.yaml @@ -0,0 +1,12 @@ +name: plant_config +description: Simulation for Peak Load Management MILP-optimized battery dispatch +plant: + plant_life: 1 + simulation: + n_timesteps: 8760 # full year (hourly) + dt: 3600 # 1-hour timesteps + timezone: -6 # MDT (UTC-6) + start_time: 2025/01/01 00:00:00 +tech_to_dispatch_connections: + - [grid_buy, battery] + - [battery, battery] diff --git a/examples/34_plm_optimized_dispatch/run_plm_optimized_dispatch.py b/examples/34_plm_optimized_dispatch/run_plm_optimized_dispatch.py new file mode 100644 index 000000000..378e7d75b --- /dev/null +++ b/examples/34_plm_optimized_dispatch/run_plm_optimized_dispatch.py @@ -0,0 +1,124 @@ +""" + +This example demonstrates demand-response storage dispatch using a rolling-horizon +MILP controller. The battery is scheduled to discharge during high-LMP peak hours +to maximize incentives. +""" + +from pathlib import Path + +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + +from h2integrate.core.utilities import build_time_series_from_plant_config +from h2integrate.core.h2integrate_model import H2IntegrateModel + + +EXAMPLE_DIR = Path(__file__).parent + + +model = H2IntegrateModel(EXAMPLE_DIR / "34_plm_optimized_dispatch.yaml") +model.setup() + + +N = model.plant_config["plant"]["simulation"]["n_timesteps"] +percentile = model.technology_config["technologies"]["battery"]["model_inputs"][ + "control_parameters" +]["signal_threshold_percentile"] + +model.run() + +lmp = np.array( + model.technology_config["technologies"]["battery"]["model_inputs"]["control_parameters"][ + "supervisory_signal" + ] +)[:N] + +n_timesteps = int(model.plant_config["plant"]["simulation"]["n_timesteps"]) +dt_seconds = int(model.plant_config["plant"]["simulation"]["dt"]) +time_index = pd.DatetimeIndex(build_time_series_from_plant_config(model.plant_config)) + +battery_power = model.prob.get_val("battery.storage_electricity_discharge", units="kW") +soc_pct = model.prob.get_val("battery.SOC", units="percent") + +controller = model.control_strategies[0] +pw_start, pw_end = controller._parse_peak_window() +pw_start_h = pw_start.hour +pw_end_h = pw_end.hour + +control_params = model.technology_config["technologies"]["battery"]["model_inputs"][ + "control_parameters" +] +event_dur_cfg = control_params.get("event_duration") + +half_td = None +if event_dur_cfg is not None: + half_td = pd.Timedelta(value=event_dur_cfg["val"], unit=event_dur_cfg["units"]) / 2 + +threshold_pct = np.percentile(lmp, percentile) +discharge_mask = battery_power > 0 + + +plt.rcParams.update({"axes.spines.top": False, "axes.spines.right": False}) +fig, axes = plt.subplots(2, 1, sharex=True, figsize=(11, 7)) +days = pd.date_range(time_index[0].normalize(), periods=14, freq="D", tz=time_index.tz) +time_window = min(n_timesteps, int(14 * 24 * 3600 / dt_seconds)) # 14 days + + +def shade_peaks(ax): + for day in days: + ax.axvspan( + day + pd.Timedelta(hours=pw_start_h), + day + pd.Timedelta(hours=pw_end_h), + color="orange", + alpha=0.10, + linewidth=0, + zorder=0, + ) + if half_td is None: + continue + pw_start_ts = day + pd.Timedelta(hours=pw_start_h) + pw_end_ts = day + pd.Timedelta(hours=pw_end_h) + in_pw = (time_index >= pw_start_ts) & (time_index <= pw_end_ts) + if not in_pw.any(): + continue + peak_idx = np.where(in_pw)[0][np.argmax(lmp[in_pw])] + peak_ts = time_index[peak_idx] + ax.axvspan( + peak_ts - half_td, + peak_ts + half_td, + color="darkorange", + alpha=0.30, + linewidth=0, + zorder=0, + ) + + +w_discharge = discharge_mask[:time_window] + +ax = axes[0] +shade_peaks(ax) +ax.plot(time_index[:time_window], lmp[:time_window], color="steelblue", linewidth=1.0) +ax.axhline(threshold_pct, color="k", linestyle="--", linewidth=0.8) +ax.plot( + time_index[:time_window][w_discharge], + lmp[:time_window][w_discharge], + "r*", + markersize=8, + zorder=5, +) +ax.set_ylabel("LMP ($/MWh)", fontsize=8) +ax.set_ylim(bottom=0) + +ax = axes[1] +shade_peaks(ax) +ax.plot(time_index[:time_window], soc_pct[:time_window], color="g", linewidth=1.0) +ax.axhline(90, color="gray", linestyle=":", linewidth=0.7) +ax.axhline(10, color="gray", linestyle=":", linewidth=0.7) +ax.set_ylabel("SOC (%)", fontsize=8) +ax.set_ylim([0, 105]) + + +plt.tight_layout() +plt.savefig(EXAMPLE_DIR / "plm_optimized_dispatch.png", dpi=150, bbox_inches="tight") diff --git a/examples/34_plm_optimized_dispatch/tech_config.yaml b/examples/34_plm_optimized_dispatch/tech_config.yaml new file mode 100644 index 000000000..4a9a7d909 --- /dev/null +++ b/examples/34_plm_optimized_dispatch/tech_config.yaml @@ -0,0 +1,59 @@ +name: technology_config +description: 300 kW / 2 MWh battery with Peak Load Management MILP-optimized dispatch controller +technologies: + battery: + performance_model: + model: StoragePerformanceModel + cost_model: + model: ATBBatteryCostModel + control_strategy: + model: PeakLoadManagementOptimizedStorageController + model_inputs: + shared_parameters: + commodity: electricity + commodity_rate_units: kW + max_charge_rate: 300.0 # kW rated power + max_capacity: 2000.0 # kWh usable capacity + max_soc_fraction: 0.90 + min_soc_fraction: 0.10 + init_soc_fraction: 0.90 + charge_efficiency: 0.95 + discharge_efficiency: 0.95 + performance_parameters: + demand_profile: 0.0 + control_parameters: + system_commodity_interface_limit: 1.0e9 + supervisory_signal: !include demand_profiles/supervisory_signal.yaml + peak_window: + start: 12:00:00 + end: 20:00:00 + performance_incentive_per_event: 16800.0 # $/event + n_max_events: 10 # maximum discharge events per month + signal_threshold_percentile: 95.0 # only dispatch when LMP >= this percentile + n_control_window_hours: 24 # hours; converted to timesteps using simulation dt + event_duration: # omit or set to null to use static peak_window + units: h # any pandas timedelta unit: h, min, s, + val: 4 # battery eligible +/ - val h around the daily peak + min_peak_separation: # omit or set to null to allow any peak spacing + units: h + val: 4 # drop any eligible peak within this distance of a higher peak + round_digits: 4 + cost_parameters: + cost_year: 2024 + energy_capex: 408 # $/kWh + power_capex: 379 # $/kW + opex_fraction: 0.025 + grid_buy: + performance_model: + model: GridPerformanceModel + cost_model: + model: GridCostModel + model_inputs: + shared_parameters: + interconnection_size: 100000 # kW + cost_parameters: + cost_year: 2024 + fixed_interconnection_cost: 0.0 + interconnection_capex_per_kw: 0.0 + interconnection_opex_per_kw: 0.0 + electricity_buy_price: 0.09 # $/kWh diff --git a/examples/test/test_all_examples.py b/examples/test/test_all_examples.py index 69b3e40a3..00d4a48f3 100644 --- a/examples/test/test_all_examples.py +++ b/examples/test/test_all_examples.py @@ -2984,3 +2984,50 @@ def test_peak_load_management_example(subtests, temp_copy_of_example): ) grid_purchase = model.prob.get_val("grid_buy.electricity_out", units="kW") assert battery_unmet_demand.sum() == pytest.approx(grid_purchase.sum(), rel=1e-3) + + +@pytest.mark.integration +@pytest.mark.parametrize( + "example_folder,resource_example_folder", [("34_plm_optimized_dispatch", None)] +) +def test_plm_optimized_dispatch_example(subtests, temp_copy_of_example): + example_folder = temp_copy_of_example + + # Create a H2Integrate model + model = H2IntegrateModel(example_folder / "34_plm_optimized_dispatch.yaml") + model.setup() + + # Run the model + model.run() + + battery_power = model.prob.get_val("battery.storage_electricity_discharge", units="kW") + soc_pct = model.prob.get_val("battery.SOC", units="percent") + + with subtests.test("Check battery power is discharging at some point"): + assert (battery_power >= 0).all() + + with subtests.test("Check SOC is between 10 and 90%"): + assert (soc_pct >= 10 - 1e-2).all() + assert (soc_pct <= 90 + 1e-2).all() + + with subtests.test("Check battery CAPEX"): + battery_capex = model.prob.get_val("battery.CapEx", units="USD")[0] + assert pytest.approx(battery_capex, rel=1e-6) == 929700.0 + + with subtests.test("Check battery OPEX"): + battery_opex = model.prob.get_val("battery.OpEx", units="USD/year")[0] + assert pytest.approx(battery_opex, rel=1e-1) == 23242.5 + + with subtests.test("Check number of discharge events"): + # With the given demand profile and battery size, there should be 2 discharge events + num_discharge_events = np.sum(battery_power > 1e-3) # Count timesteps with discharge + assert num_discharge_events == 588 + + with subtests.test("Check total energy discharged"): + total_energy_discharged = battery_power.sum() * (1 / 60) # kWh, 1 min timestep + assert pytest.approx(total_energy_discharged, rel=1e-2) == 2428.0 + + with subtests.test("Check total energy charged"): + battery_charge = model.prob.get_val("battery.storage_electricity_charge", units="kW") + total_energy_charged = battery_charge.sum() * (1 / 60) # kWh, 1 min timestep + assert pytest.approx(total_energy_charged, rel=1e-3) == -2663.0 diff --git a/h2integrate/control/control_strategies/storage/plm_optimized_storage_controller.py b/h2integrate/control/control_strategies/storage/plm_optimized_storage_controller.py new file mode 100644 index 000000000..30cbbb80e --- /dev/null +++ b/h2integrate/control/control_strategies/storage/plm_optimized_storage_controller.py @@ -0,0 +1,753 @@ +import math +from typing import Any +from datetime import datetime + +import numpy as np +import pandas as pd +import pyomo.environ as pyomo +from attrs import field, define +from pyomo.opt import SolverStatus, TerminationCondition + +from h2integrate.core.utilities import merge_shared_inputs, build_time_series_from_plant_config +from h2integrate.core.validators import range_val +from h2integrate.control.control_strategies.controller_opt_problem_state import DispatchProblemState +from h2integrate.control.control_strategies.pyomo_storage_controller_baseclass import ( + SolverOptions, + PyomoStorageControllerBaseClass, + PyomoStorageControllerBaseConfig, +) + + +@define +class PeakLoadManagementOptimizedControllerConfig(PyomoStorageControllerBaseConfig): + """Configuration for the Peak Load Management optimized storage controller. + + Inherits base fields from ``PyomoStorageControllerBaseConfig``: + ``max_capacity``, ``max_soc_fraction``, ``min_soc_fraction``, + ``init_soc_fraction``, ``n_control_window_hours``, ``commodity``, + ``commodity_rate_units``, ``tech_name``, + ``system_commodity_interface_limit``, ``round_digits``. + + Attributes: + max_charge_rate (float): Maximum charge and discharge rate (kW). + supervisory_signal (list[float]): Price, demand, or price*demand + forecast time series. The rolling horizon solver uses one window of + length ``n_control_window_hours`` per solve. + peak_window (dict): Hours eligible for dispatch. Keys ``'start'`` + and ``'end'`` must be strings in ``HH:MM:SS`` format. + performance_incentive (float): Incentive revenue in $/kWh. + Mutually exclusive with ``performance_incentive_per_event``. + performance_incentive_per_event (float): Incentive revenue in + $/event. Converted internally to an effective $/kWh rate using + ``steps_per_event``, ``dt``, and ``P_max``: + ``incentive_kWh = incentive_event / (steps_per_event * dt_h * P_max)``. + Mutually exclusive with ``performance_incentive``. + charge_efficiency (float): Charge efficiency in [0, 1]. + Defaults to 1.0. + discharge_efficiency (float): Discharge efficiency in [0, 1]. + Defaults to 1.0. + n_max_events (int): Maximum discharge events per calendar month. + Defaults to 10. + n_control_window_hours (float): Rolling window size in **hours**. + Converted to an integer timestep count during ``setup()`` + using the simulation ``dt``, so the same value works at any + resolution. Example: ``10`` at a 30-min ``dt`` gives a + 20-timestep window. Defaults to ``24``. + signal_threshold_percentile (float): Percentile (0-100) used to + compute the signal threshold for each rolling window. Only + timesteps at or above this percentile of the window signal are + eligible for dispatch. Defaults to 0.0 (all timesteps eligible). + event_duration (dict): Total dispatch-event duration + expressed as a ``{units, val}`` dict, where ``units`` is any + pandas timedelta unit string (e.g. ``'h'``, ``'min'``, + ``'s'``) and ``val`` is the numeric amount. When set, the + peak-signal timestep within ``peak_window`` is located and + every timestep within ``event_duration / 2`` of + that peak is marked eligible (the window may extend + beyond the static ``peak_window`` boundaries). When ``None`` + (default) the static ``peak_window`` mask is used unchanged. + Example: ``{units: 'h', val: 4}`` is +/- 2 h around the daily peak. + min_peak_separation (dict): Minimum separation between eligible + peaks, expressed as a ``{units, val}`` dict like + ``event_duration``. When set, the eligible timesteps identified + by ``signal_threshold_percentile`` are treated as peaks and + the first peak is chosen as eligible. + """ + + max_charge_rate: float = field() + supervisory_signal: list = field() + peak_window: dict = field() + performance_incentive: float = field(default=None) + performance_incentive_per_event: float = field(default=None) + charge_efficiency: float = field(validator=range_val(0, 1), default=1.0) + discharge_efficiency: float = field(validator=range_val(0, 1), default=1.0) + n_max_events: int = field(default=10) + n_control_window_hours: float = field(default=24.0) + signal_threshold_percentile: float = field(default=0.0, validator=range_val(0, 100)) + event_duration: dict = field(default=None) + min_peak_separation: dict = field(default=None) + + def __attrs_post_init__(self): + # Make sure n_control_window_hours is an int + self.n_control_window_hours = int(math.ceil(self.n_control_window_hours)) + super().__attrs_post_init__() + + both_set = ( + self.performance_incentive is not None + and self.performance_incentive_per_event is not None + ) + neither_set = ( + self.performance_incentive is None and self.performance_incentive_per_event is None + ) + if both_set or neither_set: + raise ValueError( + "Exactly one of 'performance_incentive' ($/kWh) or " + "'performance_incentive_per_event' ($/event) must be set." + ) + + for field_name, value in ( + ("event_duration", self.event_duration), + ("min_peak_separation", self.min_peak_separation), + ): + if value is not None: + for key in ("units", "val"): + if key not in value: + raise ValueError( + f"{field_name} is missing required key '{key}'. " + "Expected dict with 'units' (pandas timedelta unit string) " + "and 'val' (int or float)." + ) + if not isinstance(value["val"], int | float): + raise ValueError( + f"{field_name} 'val' must be a numeric value " + f"(int or float), got {type(value['val']).__name__}." + ) + + +class PeakLoadManagementOptimizedStorageController(PyomoStorageControllerBaseClass): + """Demand-response storage controller using a rolling-horizon MILP. + + Each call to the dispatch solver iterates over the full simulation in + windows of length ``n_control_window_hours``. For each window it builds + and solves a MILP that maximizes incentive revenue, then passes the + resulting dispatch commands to the performance model. The terminal SOC + of each window is carried forward as the initial SOC of the next window. + """ + + dr_model: Any + problem_state: DispatchProblemState + _time_step_bound = (300, 3600) + + def setup(self): + """Initialize config, register OpenMDAO inputs, and pre-compute static masks. + + Raises: + ValueError: If the length of the time series built from + ``plant_config`` does not match ``n_timesteps``. + """ + self.config = PeakLoadManagementOptimizedControllerConfig.from_dict( + merge_shared_inputs(self.options["tech_config"]["model_inputs"], "control") + ) + + self.add_input( + "max_charge_rate", + val=self.config.max_charge_rate, + units=self.config.commodity_rate_units, + desc="Maximum charge/discharge rate P_max", + ) + self.add_input( + "storage_capacity", + val=self.config.max_capacity, + units=f"{self.config.commodity_rate_units}*h", + desc="Total storage capacity", + ) + + sim = self.options["plant_config"]["plant"]["simulation"] + self.n_timesteps = int(sim["n_timesteps"]) # number of "dt"s in the simulation + self.dt_seconds = int(sim["dt"]) # length of each timestep in seconds + + # n_control_window_hours is stored in hours; convert to timesteps now that dt is known. + n_cw_steps = max(1, int(round(self.config.n_control_window_hours * 3600 / self.dt_seconds))) + object.__setattr__(self.config, "n_control_window_hours", n_cw_steps) + + super().setup() + + self.updated_initial_soc = self.config.init_soc_fraction + + self.commodity_info = { + "commodity_name": self.config.commodity, + "commodity_storage_units": self.config.commodity_rate_units, + } + + self.time_index = build_time_series_from_plant_config( + self.options["plant_config"] + ) # DatetimeIndex of length n_timesteps + + if len(self.time_index) != self.n_timesteps: + raise ValueError( + f"Time series length {len(self.time_index)} != n_timesteps {self.n_timesteps}" + ) + + self.in_peak_window = self._compute_peak_window_mask() # bool array, shape (T,) + self.month_ids = self._compute_month_ids() # int array, shape (T,) + + # Computes the number of timesteps in an event based on event_duration and dt_seconds, + # rounded to nearest int and at least 1. + if self.config.event_duration is not None: + self.steps_per_event: int = max( + 1, + math.ceil( + pd.Timedelta( + value=self.config.event_duration["val"], + unit=self.config.event_duration["units"], + ).total_seconds() + / self.dt_seconds + ), + ) + else: + self.steps_per_event = 1 + + def initialize_parameters(self, inputs): + """Sync OpenMDAO inputs into the config. + + Args: + inputs (dict): OpenMDAO inputs dict. Recognized keys are + ``'max_charge_rate'`` and ``'storage_capacity'``. + """ + if "max_charge_rate" in inputs: + object.__setattr__(self.config, "max_charge_rate", float(inputs["max_charge_rate"][0])) + if "storage_capacity" in inputs: + object.__setattr__(self.config, "max_capacity", float(inputs["storage_capacity"][0])) + + def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): + """Build the DR dispatch solver and write it to discrete outputs. + + Args: + inputs (dict): OpenMDAO continuous inputs. + outputs (dict): OpenMDAO continuous outputs. + discrete_inputs (dict): OpenMDAO discrete inputs. + discrete_outputs (dict): OpenMDAO discrete outputs. The key + ``'pyomo_dispatch_solver'`` is set to the callable + returned by `pyomo_setup`. + """ + discrete_outputs["pyomo_dispatch_solver"] = self.pyomo_setup(discrete_inputs, inputs) + + def pyomo_setup(self, discrete_inputs, om_inputs): + """Return the rolling-horizon dispatch solver callable. + + Args: + discrete_inputs (dict): OpenMDAO discrete inputs. + om_inputs (dict): OpenMDAO continuous inputs. ``max_charge_rate`` + and ``storage_capacity`` are read from here so that optimizer + changes to those values are reflected in each solve. + + Returns: + callable: ``pyomo_dispatch_solver(performance_model, + performance_model_kwargs, inputs)`` that iterates over the + simulation in windows of ``n_control_window_hours`` timesteps. + For each window it: + + 1. Builds a fresh MILP from the window's signal slice. + 2. Solves the MILP with a MILP solver + 3. Calls ``performance_model`` with the resulting dispatch + commands. + 4. Carries the terminal SOC into the next window. + + Returns ``(storage_out, soc_out)`` - two ``np.ndarray`` of + length ``n_timesteps``. + """ + + P_max = float(om_inputs["max_charge_rate"][0]) + storage_capacity = float(om_inputs["storage_capacity"][0]) + + def pyomo_dispatch_solver( + performance_model, + performance_model_kwargs, + inputs, + commodity_name=self.config.commodity, + ): + storage_out = np.zeros(self.n_timesteps) + soc_out = np.zeros(self.n_timesteps) + + # Track events used per calendar month so the monthly cap is + # respected across window boundaries. + events_used_per_month = {} + + n_w: int = int(self.config.n_control_window_hours) + # Compute the starting index of each rolling window. + window_start_indices = list(range(0, self.n_timesteps, n_w)) + + for window_start in window_start_indices: + window_len: int = min(n_w, self.n_timesteps - window_start) + month_ids_w = self.month_ids[window_start : window_start + window_len] + # Since this is a rolling horizon, we need to compute the remaining budget + # for the next optimization call + remaining_budget = { + int(m): max( + 0, + self.config.n_max_events + - (events_used_per_month[int(m)] if int(m) in events_used_per_month else 0), + ) + for m in np.unique(month_ids_w) + } + # Construct the MILP for this window + self.dr_model = self._build_dr_model( + window_start=window_start, + window_len=window_len, + init_soc=self.updated_initial_soc, + remaining_budget=remaining_budget, + P_max=P_max, + storage_capacity=storage_capacity, + ) + self.problem_state = DispatchProblemState() + + # Solve the optimzation problem + self.solve_dispatch_model( + start_time=window_start, + n_days=int(math.ceil(self.n_timesteps * self.dt_seconds / 86400)), + ) + + # Count new discharge events to track the monthly cap. + for t in range(window_len): + discharging = pyomo.value(self.dr_model.discharge[t]) > 0.5 + prev_discharging = t > 0 and pyomo.value(self.dr_model.discharge[t - 1]) > 0.5 + # Detect the rising edge of a discharge event (0 -> 1) and count + # it if it occurs in this window. + if discharging and not prev_discharging: + month = int(month_ids_w[t]) + if month not in events_used_per_month: + events_used_per_month[month] = 0 + events_used_per_month[month] += 1 + + # Run the performance model for this window. + storage_out_window, soc_window = performance_model( + self._get_storage_dispatch_commands(), + **performance_model_kwargs, + sim_start_index=window_start, + ) + + # Performance model returns SOC in percent. + self.updated_initial_soc = np.clip( + soc_window[-1] / 100.0, + self.config.min_soc_fraction, + self.config.max_soc_fraction, + ) + + storage_out[window_start : window_start + window_len] = storage_out_window + soc_out[window_start : window_start + window_len] = soc_window + + return storage_out, soc_out + + return pyomo_dispatch_solver + + def _parse_peak_window(self) -> tuple: + """Parse the ``peak_window`` config entry into ``datetime.time`` objects. + + Accepts values either as ``HH:MM:SS`` strings or as plain integers + (seconds since midnight). PyYAML parses unquoted ``HH:MM:SS`` values + as sexagesimal integers, so both forms are equivalent in YAML. + + Returns: + tuple[datetime.time, datetime.time]: ``(start, end)`` times. + + Raises: + ValueError: If ``'start'`` or ``'end'`` keys are missing, or + if a value is neither a valid ``HH:MM:SS`` string nor an integer. + """ + pw = dict(self.config.peak_window) + if "start" not in pw or "end" not in pw: + raise ValueError("peak_window must contain 'start' and 'end' keys") + for key in ("start", "end"): + val = pw[key] + if isinstance(val, int | float): + total_seconds = int(val) + hours, remainder = divmod(total_seconds, 3600) + minutes, seconds = divmod(remainder, 60) + pw[key] = datetime.min.replace(hour=hours, minute=minutes, second=seconds).time() + elif isinstance(val, str) and len(val.split(":")) == 3: + pw[key] = datetime.strptime(val, "%H:%M:%S").time() + else: + raise ValueError( + f"peak_window '{key}' must be HH:MM:SS string or integer seconds, got {val!r}." + ) + return pw["start"], pw["end"] + + def _compute_peak_window_mask(self) -> np.ndarray: + """Build a boolean mask that is ``True`` for timesteps inside the peak window. + + Returns: + np.ndarray: Boolean array of shape ``(n_timesteps,)``. + + Raises: + ValueError: If ``peak_window`` end time is before start time. + """ + start, end = self._parse_peak_window() + times = pd.DatetimeIndex(self.time_index).time + if end < start: + raise ValueError("peak_window end time must be after start time.") + return np.array([start <= t < end for t in times]) + + def _compute_month_ids(self) -> np.ndarray: + """Return the calendar month index (1-12) for each timestep. + + Returns: + np.ndarray: Integer array of shape ``(n_timesteps,)``. + """ + return pd.DatetimeIndex(self.time_index).month.to_numpy() + + def _compute_eligible_mask( + self, + signal_window: np.ndarray, + dispatch_mask: np.ndarray | None = None, + ) -> np.ndarray: + """Build a boolean mask for timesteps whose signal meets the dispatch threshold. + + The threshold percentile is computed from ``signal_window`` values + that fall inside ``dispatch_mask`` (i.e. the current dispatch + window). + When ``dispatch_mask`` is ``None`` the full ``signal_window`` is + used. When ``signal_threshold_percentile`` is 0.0 all timesteps + are eligible. + If there are multiple timesteps above the threshold within a window and + ``min_peak_separation`` is set, only the first one is eligible. + + Args: + signal_window (np.ndarray): Signal values for the current + rolling window. + dispatch_mask (np.ndarray | None): Boolean mask of shape + ``(len(signal_window),)`` indicating which timesteps + belong to the current dispatch window. Defaults to + ``None`` (use full window). + + Returns: + np.ndarray: Boolean array of shape ``(len(signal_window),)``. + ``True`` where ``signal_t >= threshold``. + """ + # Use all the timesteps in the window if no dispatch_mask is provided, otherwise restrict + # to the dispatch window + mask = ( + dispatch_mask if dispatch_mask is not None else np.ones(len(signal_window), dtype=bool) + ) + + # If the threshold percentile is 0 or there are dispatch_window is all 0s + # all timesteps are eligible + if self.config.signal_threshold_percentile == 0.0 or not mask.any(): + return mask.copy() + + # Keep only the timesteps where the signal is above the threshold computed from the + # dispatch window + threshold = np.percentile(signal_window[mask], self.config.signal_threshold_percentile) + eligible = mask & (signal_window >= threshold) + + if self.config.min_peak_separation is not None: + sep_steps = math.ceil( + pd.Timedelta( + value=self.config.min_peak_separation["val"], + unit=self.config.min_peak_separation["units"], + ).total_seconds() + / self.dt_seconds + ) + # Keep the first peak; drop any subsequent peaks + # within sep_steps of the last kept one. + # This is a greedy choice but subsequent iterations will + # use a smarter logic + kept = [] + for idx in np.where(eligible)[0]: + if not kept or int(idx) - kept[-1] >= sep_steps: + # Won't enter this condition if the peaks are too close together + kept.append(int(idx)) + eligible = np.zeros(len(signal_window), dtype=bool) + eligible[kept] = True + + return eligible + + def _compute_event_window_mask( + self, + eligible_mask: np.ndarray, + ) -> np.ndarray: + """Expand each eligible peak timestep by +/- event_duration/2. + + Every True timestep in ``eligible_mask`` is + treated as a peak and all timesteps within ``event_duration / 2`` + of it are marked eligible. When ``event_duration`` is ``None`` + returns ``eligible_mask`` unchanged. + + Args: + eligible_mask (np.ndarray): Boolean mask of peak timesteps, + shape ``(window_len,)``. + + Returns: + np.ndarray: Boolean mask of shape ``(window_len,)``. + """ + if self.config.event_duration is None: + return eligible_mask.copy() + + half_event_steps = self.steps_per_event / 2 + peak_indices = np.where(eligible_mask)[0] + event_mask = np.zeros(len(eligible_mask), dtype=bool) + for peak in peak_indices: + near_peak = np.abs(np.arange(len(eligible_mask)) - peak) <= half_event_steps + event_mask |= near_peak + return event_mask + + def _build_dr_model( + self, + window_start: int, + window_len: int, + init_soc: float, + remaining_budget: dict, + P_max: float, + storage_capacity: float, + ) -> pyomo.ConcreteModel: + """Build the DR MILP for a single rolling window. + + Decision variables + ------------------ + discharge[t] : binary + Event indicator — 1 if a discharge event is active at timestep t. + Used for event counting and window feasibility constraints only. + charge[t] : binary + Event indicator — 1 if a charge event is active at timestep t. + p_discharge[t] : continuous in [0, P_max] + Actual discharge power (kW). Linked to the binary via the + McCormick upper-bound constraint ``p_discharge[t] <= P_max * discharge[t]``. + p_charge[t] : continuous in [0, P_max] + Actual charge power (kW). Linked via ``p_charge[t] <= P_max * charge[t]``. + soc[t] : continuous in [soc_min, soc_max] + State of charge (fraction). + + Args: + window_start (int): Timestep index of the first timestep + in this window. + window_len (int): Number of timesteps in this window. + init_soc (float): State-of-charge fraction at the start of + this window. + remaining_budget (dict): Mapping of ``month_id (int)`` to + remaining event slots for that month. Computed by + subtracting events already dispatched in earlier windows + from ``n_max_events``, so the monthly cap is respected + across windows. + P_max (float): Maximum charge/discharge rate (kW), taken + from OpenMDAO inputs so optimizer changes are reflected. + storage_capacity (float): Total storage capacity (kWh), taken + from OpenMDAO inputs so optimizer changes are reflected. + + Returns: + pyomo.ConcreteModel: Fully formed MILP ready to solve. + """ + m: Any = pyomo.ConcreteModel(name="plm_dr") + + E_max = storage_capacity * (self.config.max_soc_fraction - self.config.min_soc_fraction) + eta_c = self.config.charge_efficiency + eta_d = self.config.discharge_efficiency + soc_max = self.config.max_soc_fraction + soc_min = self.config.min_soc_fraction + dt_hours = self.dt_seconds / 3600.0 + + # This converts the incentive from $/event to an effective $/kWh + # rate based on the number of timesteps in an event (steps_per_event), + # the length of each timestep in hours (dt_hours), and the max power (P_max). + if self.config.performance_incentive_per_event is not None: + incentive = self.config.performance_incentive_per_event / ( + self.steps_per_event * dt_hours * P_max + ) + else: + incentive = self.config.performance_incentive + N_max = self.config.n_max_events + + # Only the timesteps within the current window are relevant + w = slice(window_start, window_start + window_len) + in_peak_window_w = self.in_peak_window[w] + month_ids_w = self.month_ids[w] + signal_w = np.asarray(self.config.supervisory_signal, dtype=float)[w] + + # Eligible timesteps for discharge based on percentile + eligible_t_w = self._compute_eligible_mask(signal_w, in_peak_window_w) + # Expand eligible timesteps into event windows based on event_duration + dispatch_window_w = self._compute_event_window_mask(eligible_t_w) + eligible_t_w = dispatch_window_w + + months_in_window = np.unique(month_ids_w).tolist() + + # Sets we need to iterate on in the constraints and objective + m.T = pyomo.Set(initialize=range(window_len), doc="Timesteps in window") + m.M = pyomo.Set(initialize=months_in_window, doc="Months in window") + + ## Variables + # Binary event indicators- used for event counting and window constraints. + m.discharge = pyomo.Var( + m.T, domain=pyomo.Binary, doc="1 if a discharge event is active at timestep t" + ) + m.charge = pyomo.Var( + m.T, domain=pyomo.Binary, doc="1 if a charge event is active at timestep t" + ) + # Actual kW dispatched each timestep. + m.p_discharge = pyomo.Var( + m.T, + domain=pyomo.NonNegativeReals, + bounds=(0, P_max), + doc="Discharge power (kW) at timestep t", + ) + m.p_charge = pyomo.Var( + m.T, + domain=pyomo.NonNegativeReals, + bounds=(0, P_max), + doc="Charge power (kW) at timestep t", + ) + m.soc = pyomo.Var( + m.T, + domain=pyomo.NonNegativeReals, + bounds=(soc_min, soc_max), + doc="State of charge SoC_t", + ) + + # Incentive revenue is earned for every kWh discharged. + m.objective = pyomo.Objective( + expr=-incentive * dt_hours * sum(m.p_discharge[t] for t in m.T), + sense=pyomo.minimize, + ) + + ## Constraints + # Discharge can only occur during the dispatch window. + m.peak_window_only = pyomo.Constraint( + m.T, + rule=lambda mdl, t: ( + mdl.discharge[t] == 0 if not dispatch_window_w[t] else pyomo.Constraint.Skip + ), + ) + + # Discharge can only occur at eligible timesteps. + m.high_signal_only = pyomo.Constraint( + m.T, + rule=lambda mdl, t: mdl.discharge[t] <= int(eligible_t_w[t]), + ) + + # There is a limit on the number of events, not discharge timesteps. + # However, we know the number of timesteps in the event from steps_per_event, + # so we can indirectly limit the number of discharge timesteps in each month + # by multiplying the event cap by steps_per_event. + def max_events_rule(mdl, month): + ts_in_month = [t for t in mdl.T if month_ids_w[t] == month] + if not ts_in_month: + return pyomo.Constraint.Skip + budget_steps = ( + remaining_budget[month] if month in remaining_budget else N_max + ) * self.steps_per_event + return sum(mdl.discharge[t] for t in ts_in_month) <= budget_steps + + m.max_events = pyomo.Constraint(m.M, rule=max_events_rule) + + # Power is zero when the binary is 0, and at most P_max when 1. + m.discharge_power_link = pyomo.Constraint( + m.T, + rule=lambda mdl, t: mdl.p_discharge[t] <= P_max * mdl.discharge[t], + ) + m.charge_power_link = pyomo.Constraint( + m.T, + rule=lambda mdl, t: mdl.p_charge[t] <= P_max * mdl.charge[t], + ) + + m.soc_init = pyomo.Constraint(expr=m.soc[0] == init_soc) + + # Dynamics of the battery SOC evolution. + def soc_evolution_rule(mdl, t): + if t == 0: + return pyomo.Constraint.Skip + return mdl.soc[t] == ( + mdl.soc[t - 1] + + eta_c * mdl.p_charge[t] * dt_hours / E_max + - mdl.p_discharge[t] * dt_hours / (eta_d * E_max) + ) + + m.soc_evolution = pyomo.Constraint(m.T, rule=soc_evolution_rule) + + # Can't charge and discharge at the same time. + m.no_simultaneous = pyomo.Constraint( + m.T, + rule=lambda mdl, t: mdl.discharge[t] + mdl.charge[t] <= 1, + ) + + # Can't charge in the dispatch window. + m.no_charge_in_window = pyomo.Constraint( + m.T, + rule=lambda mdl, t: ( + mdl.charge[t] == 0 if dispatch_window_w[t] else pyomo.Constraint.Skip + ), + ) + + return m + + def solve_dispatch_model(self, start_time: int = 0, n_days: int = 0): + """Solve the DR MILP for the current window and record solver metrics. + + Args: + start_time (int): Timestep index of the window start. + Used only for error messages and metrics. Defaults to 0. + n_days (int): Total simulation days. Passed to + ``DispatchProblemState.store_problem_metrics``. + Defaults to 0. + + Raises: + RuntimeError: If solver returns a not OK status or an + unacceptable termination condition. + """ + + solver_results = self.glpk_solve_call(self.dr_model) + + status = solver_results.solver.status + tc = solver_results.solver.termination_condition + acceptable = ( + TerminationCondition.optimal, + TerminationCondition.feasible, + TerminationCondition.maxTimeLimit, + ) + if status != SolverStatus.ok or tc not in acceptable: + raise RuntimeError( + f"PLM MILP solver failed at window start={start_time}: " + f"status={status}, termination={tc}. " + f"init_soc={self.updated_initial_soc:.4f}, " + f"window_len={len(list(self.dr_model.T))}" + ) + + self.problem_state.store_problem_metrics( + solver_results, + start_time, + n_days, + pyomo.value(self.dr_model.objective), + ) + + @staticmethod + def glpk_solve_call( + pyomo_model: pyomo.ConcreteModel, + log_name: str = "", + user_solver_options: dict | None = None, + ): + """Solve a Pyomo MILP with GLPK. + + Args: + pyomo_model (pyomo.ConcreteModel): The model to solve. + log_name (str): Optional log file name passed to + ``SolverOptions``. Defaults to ``''``. + user_solver_options (dict | None): Optional overrides for + GLPK solver options. Defaults to ``None``. + + Returns: + pyomo.opt.SolverResults: Raw results object from GLPK. + """ + glpk_solver_options = {"cuts": None, "presol": None, "tmlim": 300} + solver_options = SolverOptions(glpk_solver_options, log_name, user_solver_options, "log") + with pyomo.SolverFactory("glpk") as solver: + results = solver.solve(pyomo_model, options=solver_options.constructed, tee=False) + return results + + def _get_storage_dispatch_commands(self) -> list: + """Net dispatch commands for the solved window. + + Returns: + list[float]: ``p_discharge_t - p_charge_t`` (kW) for each timestep + in the solved window. Positive = discharge, negative = charge. + """ + return [ + pyomo.value(self.dr_model.p_discharge[t]) - pyomo.value(self.dr_model.p_charge[t]) # type: ignore[index] + for t in self.dr_model.T + ] diff --git a/h2integrate/control/control_strategies/storage/test/test_plm_optimized_storage_controller.py b/h2integrate/control/control_strategies/storage/test/test_plm_optimized_storage_controller.py new file mode 100644 index 000000000..fcb808eb0 --- /dev/null +++ b/h2integrate/control/control_strategies/storage/test/test_plm_optimized_storage_controller.py @@ -0,0 +1,550 @@ +from types import SimpleNamespace + +import numpy as np +import pandas as pd +import pytest +import openmdao.api as om +import pyomo.environ as pyomo + +from h2integrate.storage.storage_performance_model import StoragePerformanceModel +from h2integrate.control.control_strategies.storage.plm_optimized_storage_controller import ( + PeakLoadManagementOptimizedControllerConfig, + PeakLoadManagementOptimizedStorageController, +) + + +def _make_controller(): + return object.__new__(PeakLoadManagementOptimizedStorageController) + + +def _make_controller_with_config(config, n_timesteps=24, dt_seconds=3600): + """Build a controller with pre-computed masks, bypassing OpenMDAO setup.""" + controller = _make_controller() + controller.config = config + controller.dt_seconds = dt_seconds + controller.updated_initial_soc = config.init_soc_fraction + controller.time_index = pd.date_range("2024-01-01", periods=n_timesteps, freq="h") + controller.in_peak_window = controller._compute_peak_window_mask() + controller.month_ids = controller._compute_month_ids() + if config.event_duration is not None: + controller.steps_per_event = max( + 1, + int( + round( + pd.Timedelta( + value=config.event_duration["val"], + unit=config.event_duration["units"], + ).total_seconds() + / dt_seconds + ) + ), + ) + else: + controller.steps_per_event = 1 + return controller + + +@pytest.fixture +def base_config(): + n = 24 + return PeakLoadManagementOptimizedControllerConfig( + max_capacity=10.0, + max_soc_fraction=1.0, + min_soc_fraction=0.0, + init_soc_fraction=1.0, + n_control_window_hours=n, + commodity="electricity", + commodity_rate_units="kW", + tech_name="battery", + system_commodity_interface_limit=100.0, + max_charge_rate=1.0, + supervisory_signal=list(range(n)), + peak_window={"start": "08:00:00", "end": "18:00:00"}, + performance_incentive=10.0, + n_max_events=24, + signal_threshold_percentile=0.0, + ) + + +@pytest.mark.unit +def test_parse_peak_window(subtests): + controller = _make_controller() + controller.config = SimpleNamespace(peak_window={"start": "08:00:00", "end": "18:40:20"}) + start, end = controller._parse_peak_window() + with subtests.test("start hour"): + assert start.hour == 8 + with subtests.test("start minute"): + assert start.minute == 0 + with subtests.test("start second"): + assert start.second == 0 + with subtests.test("end hour"): + assert end.hour == 18 + with subtests.test("end minute"): + assert end.minute == 40 + with subtests.test("end second"): + assert end.second == 20 + + +@pytest.mark.unit +def test_parse_peak_window_invalid_format(): + controller = _make_controller() + controller.config = SimpleNamespace(peak_window={"start": "08", "end": "18:40:20"}) + with pytest.raises( + ValueError, + ): + controller._parse_peak_window() + + +@pytest.mark.unit +def test_parse_peak_window_missing_key_raises(): + controller = _make_controller() + controller.config = SimpleNamespace(peak_window={"start": "08:00:00"}) + with pytest.raises(ValueError, match="peak_window must contain 'start' and 'end' keys"): + controller._parse_peak_window() + + +@pytest.mark.unit +def test_compute_peak_window_mask(subtests): + controller = _make_controller() + controller.config = SimpleNamespace(peak_window={"start": "00:00:00", "end": "02:00:00"}) + controller.time_index = pd.date_range("2024-01-01", periods=24, freq="h") + mask = controller._compute_peak_window_mask() + expected = np.array([i < 2 for i in range(24)]) + with subtests.test("Returns ndarray"): + assert isinstance(mask, np.ndarray) + with subtests.test("Correct values"): + assert np.array_equal(mask, expected) + + +@pytest.mark.unit +def test_compute_month_ids(): + controller = _make_controller() + controller.time_index = pd.date_range("2024-01-01", periods=744 + 696 + 744, freq="h") + month_ids = controller._compute_month_ids() + expected = np.array([1] * 744 + [2] * 696 + [3] * 744) + assert np.array_equal(month_ids, expected), f"Expected {expected} but got {month_ids}" + + +@pytest.mark.unit +def test_compute_eligible_mask_zero_percentile_all_eligible(subtests): + """All timesteps are eligible when signal_threshold_percentile=0.""" + controller = _make_controller() + controller.config = SimpleNamespace(signal_threshold_percentile=0.0, min_peak_separation=None) + signal = np.array([1.0, 5.0, 3.0, 2.0, 8.0]) + mask = controller._compute_eligible_mask(signal) + with subtests.test("_compute_eligible_mask Returns ndarray"): + assert isinstance(mask, np.ndarray) + with subtests.test("_compute_eligible_mask returns Bool dtype"): + assert mask.dtype == bool + with subtests.test("_compute_eligible_mask returns correct length"): + assert len(mask) == len(signal) + with subtests.test("_compute_eligible_mask marks all as eligible when percentile=0`"): + assert mask.all() + + +@pytest.mark.unit +def test_compute_eligible_mask_50th_percentile(): + """Only values at or above the 50th percentile are eligible.""" + controller = _make_controller() + controller.config = SimpleNamespace(signal_threshold_percentile=50.0, min_peak_separation=None) + signal = np.array([1.0, 2.0, 3.0, 4.0, 5.0]) + mask = controller._compute_eligible_mask(signal) + expected = signal >= np.percentile(signal, 50.0) + assert np.array_equal(mask, expected), f"Expected {expected} but got {mask}" + + +@pytest.mark.unit +def test_compute_eligible_mask_100th_percentile_only_max_eligible(): + """Only the maximum value(s) are eligible at percentile=100.""" + controller = _make_controller() + controller.config = SimpleNamespace(signal_threshold_percentile=100.0, min_peak_separation=None) + signal = np.array([1.0, 2.0, 10.0, 3.0, 10.0]) + mask = controller._compute_eligible_mask(signal) + expected = np.array([False, False, True, False, True]) + assert np.array_equal(mask, expected), f"Expected {expected} but got {mask}" + + +@pytest.mark.unit +def test_compute_eligible_mask_uniform_signal_all_eligible(): + """All timesteps are eligible when the signal is uniform, regardless of percentile.""" + controller = _make_controller() + controller.config = SimpleNamespace(signal_threshold_percentile=75.0, min_peak_separation=None) + signal = np.full(10, 5.0) + mask = controller._compute_eligible_mask(signal) + assert mask.all(), f"Expected all True but got {mask}" + + +@pytest.mark.regression +def test_optimizer_dispatch_only_in_peak_window(subtests, base_config): + """Solver must never set 1 outside the peak window.""" + controller = _make_controller_with_config(base_config) + model = controller._build_dr_model( + window_start=0, + window_len=24, + init_soc=base_config.init_soc_fraction, + remaining_budget={1: base_config.n_max_events}, + P_max=base_config.max_charge_rate, + storage_capacity=base_config.max_capacity, + ) + + PeakLoadManagementOptimizedStorageController.glpk_solve_call(model) + + peak_start, peak_end = controller._parse_peak_window() + for t in range(24): + hour = pd.Timestamp("2024-01-01") + pd.Timedelta(hours=t) + in_window = peak_start <= hour.time() <= peak_end + if not in_window: + with subtests.test(f"No discharge outside peak window at t={t}"): + assert pyomo.value(model.discharge[t]) < 1e-3 # type: ignore[index] + + +@pytest.mark.regression +def test_optimizer_dispatch_only_on_eligible_timesteps(subtests, base_config): + """Solver must never set 1 on ineligible timesteps.""" + controller = _make_controller_with_config(base_config) + model = controller._build_dr_model( + window_start=0, + window_len=24, + init_soc=base_config.init_soc_fraction, + remaining_budget={1: base_config.n_max_events}, + P_max=base_config.max_charge_rate, + storage_capacity=base_config.max_capacity, + ) + + PeakLoadManagementOptimizedStorageController.glpk_solve_call(model) + + signal = np.array(controller.config.supervisory_signal) + eligible_mask = controller._compute_eligible_mask(signal) + for t in range(24): + if not eligible_mask[t]: + with subtests.test(f"No discharge on ineligible timestep at t={t}"): + assert pyomo.value(model.discharge[t]) < 1e-3 # type: ignore[index] + + +@pytest.mark.regression +def test_optimizer_dispatch_respects_event_budget(base_config): + """Solver must never set more than n_max_events timesteps to 1.""" + controller = _make_controller_with_config(base_config) + model = controller._build_dr_model( + window_start=0, + window_len=24, + init_soc=base_config.init_soc_fraction, + remaining_budget={1: 4}, + P_max=base_config.max_charge_rate, + storage_capacity=base_config.max_capacity, + ) + + PeakLoadManagementOptimizedStorageController.glpk_solve_call(model) + + total_events = sum(pyomo.value(model.discharge[t]) for t in range(24)) # type: ignore[index] + assert total_events <= 4 + 1e-3, f"Total events {total_events} exceeds budget of 4" + + +@pytest.mark.regression +def test_optimizer_dispatch_respects_soc_constraints(subtests, base_config): + """Solver must never violate SOC constraints.""" + controller = _make_controller_with_config(base_config) + model = controller._build_dr_model( + window_start=0, + window_len=24, + init_soc=base_config.init_soc_fraction, + remaining_budget={2: base_config.n_max_events}, + P_max=base_config.max_charge_rate, + storage_capacity=base_config.max_capacity, + ) + + PeakLoadManagementOptimizedStorageController.glpk_solve_call(model) + + E_max = base_config.max_capacity * (base_config.max_soc_fraction - base_config.min_soc_fraction) + eta_c = base_config.charge_efficiency + eta_d = base_config.discharge_efficiency + dt_hours = 3600 / 3600.0 + soc = base_config.init_soc_fraction + for t in range(24): + p_charge = pyomo.value(model.p_charge[t]) # type: ignore[index] + p_discharge = pyomo.value(model.p_discharge[t]) # type: ignore[index] + if t > 0: + soc += eta_c * p_charge * dt_hours / E_max - p_discharge * dt_hours / (eta_d * E_max) + with subtests.test(f"SOC above min at t={t}"): + assert soc >= base_config.min_soc_fraction - 1e-6 + with subtests.test(f"SOC below max at t={t}"): + assert soc <= base_config.max_soc_fraction + 1e-6 + + +@pytest.mark.unit +def test_compute_eligible_mask_min_peak_separation_drops_nearby_peak(subtests): + """A later peak within min_peak_separation of an earlier peak is dropped.""" + controller = _make_controller() + controller.config = SimpleNamespace( + signal_threshold_percentile=50.0, + min_peak_separation={"units": "h", "val": 3}, + ) + controller.dt_seconds = 3600 + signal = np.array([1.0, 1.0, 1.0, 1.0, 1.0, 10.0, 1.0, 8.0, 1.0, 1.0]) + mask = controller._compute_eligible_mask(signal) + with subtests.test("First eligible peak kept"): + assert mask[0] + with subtests.test("Adjacent peak within separation dropped"): + assert not mask[1] + + +@pytest.mark.unit +def test_compute_eligible_mask_min_peak_separation_keeps_far_peaks(subtests): + """Peaks separated by more than min_peak_separation are both kept.""" + controller = _make_controller() + controller.config = SimpleNamespace( + signal_threshold_percentile=0.0, + min_peak_separation={"units": "h", "val": 3}, + ) + controller.dt_seconds = 3600 + # t=2 (signal=10) and t=6 (signal=8) are 4h apart + signal = np.array([1.0, 1.0, 10.0, 1.0, 1.0, 1.0, 8.0, 1.0, 1.0, 1.0]) + mask = controller._compute_eligible_mask(signal) + with subtests.test("First peak kept"): + assert mask[2] + with subtests.test("Distant peak also kept"): + assert mask[6] + + +@pytest.mark.unit +def test_compute_eligible_mask_min_peak_separation_none_no_pruning(): + """min_peak_separation=None leaves all percentile-eligible peaks unchanged.""" + controller = _make_controller() + controller.config = SimpleNamespace( + signal_threshold_percentile=0.0, + min_peak_separation=None, + ) + signal = np.array([1.0, 5.0, 6.0, 5.0, 1.0]) + mask = controller._compute_eligible_mask(signal) + assert mask.all(), f"Expected all True but got {mask}" + + +@pytest.mark.regression +def test_optimizer_dispatch_respects_charge_discharge_exclusivity(subtests, base_config): + """Solver must never set charge and discharge to 1 in the same timestep.""" + controller = _make_controller_with_config(base_config) + model = controller._build_dr_model( + window_start=0, + window_len=24, + init_soc=base_config.init_soc_fraction, + remaining_budget={1: base_config.n_max_events}, + P_max=base_config.max_charge_rate, + storage_capacity=base_config.max_capacity, + ) + + PeakLoadManagementOptimizedStorageController.glpk_solve_call(model) + + for t in range(24): + charge = pyomo.value(model.charge[t]) # type: ignore[index] + discharge = pyomo.value(model.discharge[t]) # type: ignore[index] + with subtests.test(f"No simultaneous charge and discharge at t={t}"): + assert not (charge > 0.5 and discharge > 0.5) + + +@pytest.mark.regression +def test_power_zero_when_binary_zero(subtests, base_config): + """p_discharge[t] must be 0 whenever discharge[t] == 0.""" + controller = _make_controller_with_config(base_config) + model = controller._build_dr_model( + window_start=0, + window_len=24, + init_soc=base_config.init_soc_fraction, + remaining_budget={1: base_config.n_max_events}, + P_max=base_config.max_charge_rate, + storage_capacity=base_config.max_capacity, + ) + + PeakLoadManagementOptimizedStorageController.glpk_solve_call(model) + + for t in range(24): + u = pyomo.value(model.discharge[t]) # type: ignore[index] + p_d = pyomo.value(model.p_discharge[t]) # type: ignore[index] + v = pyomo.value(model.charge[t]) # type: ignore[index] + p_c = pyomo.value(model.p_charge[t]) # type: ignore[index] + with subtests.test(f"p_discharge zero when binary zero at t={t}"): + if u < 0.5: + assert p_d < 1e-6, f"p_discharge[{t}]={p_d} but discharge[{t}]={u}" + with subtests.test(f"p_charge zero when binary zero at t={t}"): + if v < 0.5: + assert p_c < 1e-6, f"p_charge[{t}]={p_c} but charge[{t}]={v}" + + +@pytest.mark.regression +def test_performance_incentive_per_event_matches_equivalent_kwh_rate(subtests): + """$/event and its equivalent $/kWh rate must produce identical dispatch. + + With event_duration=2h, dt=1h, P_max=1.0 kW: + steps_per_event=2, dt_hours=1.0 + 10.0 $/event / (2 * 1.0 * 1.0) = 5.0 $/kWh + """ + common = { + "max_capacity": 10.0, + "max_soc_fraction": 1.0, + "min_soc_fraction": 0.0, + "init_soc_fraction": 1.0, + "n_control_window_hours": 24, + "commodity": "electricity", + "commodity_rate_units": "kW", + "tech_name": "battery", + "system_commodity_interface_limit": 100.0, + "max_charge_rate": 1.0, + "supervisory_signal": list(range(24)), + "peak_window": {"start": "08:00:00", "end": "18:00:00"}, + "n_max_events": 24, + "signal_threshold_percentile": 0.0, + "event_duration": {"val": 2, "units": "h"}, + } + config_kwh = PeakLoadManagementOptimizedControllerConfig(**common, performance_incentive=5.0) + config_event = PeakLoadManagementOptimizedControllerConfig( + **common, performance_incentive_per_event=10.0 + ) + + build_kwargs = { + "window_start": 0, + "window_len": 24, + "init_soc": 1.0, + "remaining_budget": {1: 24}, + "P_max": 1.0, + "storage_capacity": 10.0, + } + model_kwh = _make_controller_with_config(config_kwh)._build_dr_model(**build_kwargs) + model_event = _make_controller_with_config(config_event)._build_dr_model(**build_kwargs) + + PeakLoadManagementOptimizedStorageController.glpk_solve_call(model_kwh) + PeakLoadManagementOptimizedStorageController.glpk_solve_call(model_event) + + for t in range(24): + with subtests.test(f"dispatch match at t={t}"): + assert ( + abs( + pyomo.value(model_kwh.p_discharge[t]) # type: ignore[index] + - pyomo.value(model_event.p_discharge[t]) # type: ignore[index] + ) + < 1e-4 + ), f"Dispatch mismatch at t={t}" + + +@pytest.fixture +def om_plant_config(): + return { + "plant": { + "plant_life": 30, + "simulation": { + "n_timesteps": 24, + "dt": 3600, + "timezone": 0, + "start_time": "01/01/2024 00:00:00", + }, + }, + "tech_to_dispatch_connections": [["controller", "storage"]], + } + + +@pytest.fixture +def om_tech_config(): + n = 24 + return { + "model_inputs": { + "shared_parameters": { + "tech_name": "battery", + "commodity": "electricity", + "commodity_rate_units": "kW", + "max_charge_rate": 1.0, + "max_capacity": 10.0, + "max_soc_fraction": 1.0, + "min_soc_fraction": 0.0, + "init_soc_fraction": 1.0, + "charge_efficiency": 1.0, + "discharge_efficiency": 1.0, + }, + "performance_parameters": { + "demand_profile": 10.0, + }, + "control_parameters": { + "system_commodity_interface_limit": 1.0e9, + "supervisory_signal": np.ones(n).tolist(), + "peak_window": {"start": "02:00:00", "end": "04:00:00"}, + "performance_incentive": 10.0, + "n_max_events": 24, + "signal_threshold_percentile": 0.0, + "n_control_window_hours": n, + }, + } + } + + +@pytest.mark.regression +def test_plm_optimized_controller_om_problem_soc_bounds(subtests, om_plant_config, om_tech_config): + """Controller and StoragePerformanceModel wired as an om.Problem respect SOC bounds + and discharge only within the peak window.""" + n = om_plant_config["plant"]["simulation"]["n_timesteps"] + + prob = om.Problem() + + prob.model.add_subsystem( + name="IVC", + subsys=om.IndepVarComp(name="electricity_in", val=np.ones(n), units="kW"), + promotes=["*"], + ) + prob.model.add_subsystem( + "controller", + PeakLoadManagementOptimizedStorageController( + plant_config=om_plant_config, + tech_config=om_tech_config, + ), + promotes=["*"], + ) + prob.model.add_subsystem( + "storage", + StoragePerformanceModel( + plant_config=om_plant_config, + tech_config=om_tech_config, + ), + promotes=["*"], + ) + + prob.setup() + prob.run_model() + + soc = prob.get_val("SOC", units="unitless") + discharge = prob.get_val("storage_electricity_discharge", units="kW") + + with subtests.test("SOC never below min"): + assert np.all(soc >= 0.0 - 1e-1) + + with subtests.test("SOC never above max"): + assert np.all(soc <= 1.0 + 1e-1) + + pw = om_tech_config["model_inputs"]["control_parameters"]["peak_window"] + pw_start = pd.Timestamp(f"2024-01-01 {pw['start']}").time() + pw_end = pd.Timestamp(f"2024-01-01 {pw['end']}").time() + time_index = pd.date_range("2024-01-01", periods=n, freq="h") + for t in range(n): + in_window = pw_start <= time_index[t].time() < pw_end + if not in_window: + with subtests.test(f"No discharge outside peak window at t={t}"): + assert ( + discharge[t] <= 1e-4 + ), f"Discharge {discharge[t]:.4f} kW outside peak window at t={t}" + + with subtests.test("Discharge never negative"): + assert np.all(discharge >= -1e-4) + + with subtests.test("Discharge never above max_charge_rate"): + assert np.all(discharge <= 1.0 + 1e-4) + + with subtests.test("SOC at t=0 equal to init_soc_fraction"): + assert abs(soc[0] - 1.0) < 1e-4 + + shared = om_tech_config["model_inputs"]["shared_parameters"] + E_max = shared["max_capacity"] * (shared["max_soc_fraction"] - shared["min_soc_fraction"]) + charge = prob.get_val("storage_electricity_charge", units="kW") + expected_soc = np.zeros(n) + expected_soc[0] = shared["init_soc_fraction"] + for t in range(1, n): + expected_soc[t] = expected_soc[t - 1] + charge[t] / E_max - discharge[t] / E_max + for t in range(n): + with subtests.test(f"SOC evolution at t={t}"): + assert ( + abs(soc[t] - expected_soc[t]) < 1e-4 + ), f"SOC mismatch at t={t}: got {soc[t]:.4f}, expected {expected_soc[t]:.4f}" diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index 62e197de9..b2abecd78 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -177,6 +177,9 @@ from h2integrate.control.control_rules.storage.pyomo_storage_rule_min_operating_cost import ( PyomoRuleStorageMinOperatingCosts, ) +from h2integrate.control.control_strategies.storage.plm_optimized_storage_controller import ( + PeakLoadManagementOptimizedStorageController, +) from h2integrate.control.control_rules.converters.generic_converter_min_operating_cost import ( PyomoDispatchGenericConverterMinOperatingCosts, ) @@ -298,6 +301,7 @@ "PeakLoadManagementHeuristicOpenLoopStorageController": ( PeakLoadManagementHeuristicOpenLoopStorageController ), + "PeakLoadManagementOptimizedStorageController": (PeakLoadManagementOptimizedStorageController), "HeuristicLoadFollowingStorageController": HeuristicLoadFollowingStorageController, "OptimizedDispatchStorageController": OptimizedDispatchStorageController, "GenericDemandComponent": GenericDemandComponent,