|
18 | 18 | from deprecated import deprecated |
19 | 19 | from pyomo.environ import value |
20 | 20 |
|
| 21 | +from temoa.components import geography, technology |
| 22 | + |
21 | 23 | from .utils import get_adjusted_existing_capacity, get_capacity_factor |
22 | 24 |
|
23 | 25 | if TYPE_CHECKING: |
@@ -456,15 +458,18 @@ def capacity_constraint( |
456 | 458 | if t in model.tech_curtailment: |
457 | 459 | # If technologies are present in the curtailment set, then enough |
458 | 460 | # capacity must be available to cover both activity and curtailment. |
459 | | - return get_capacity_factor(model, r, s, d, t, v) * value( |
460 | | - model.capacity_to_activity[r, t] |
461 | | - ) * value(model.segment_fraction[s, d]) * model.v_capacity[ |
462 | | - r, p, t, v |
463 | | - ] == useful_activity + sum( |
| 461 | + curtailment = sum( |
464 | 462 | model.v_curtailment[r, p, s, d, S_i, t, v, S_o] |
465 | 463 | for S_i in model.process_inputs[r, p, t, v] |
466 | 464 | for S_o in model.process_outputs_by_input[r, p, t, v, S_i] |
467 | 465 | ) |
| 466 | + return ( |
| 467 | + get_capacity_factor(model, r, s, d, t, v) |
| 468 | + * value(model.capacity_to_activity[r, t]) |
| 469 | + * value(model.segment_fraction[s, d]) |
| 470 | + * model.v_capacity[r, p, t, v] |
| 471 | + == useful_activity + curtailment |
| 472 | + ) |
468 | 473 | else: |
469 | 474 | return ( |
470 | 475 | get_capacity_factor(model, r, s, d, t, v) |
@@ -661,3 +666,37 @@ def create_capacity_and_retirement_sets(model: TemoaModel) -> None: |
661 | 666 | for r, p, t in model.active_capacity_available_rpt |
662 | 667 | for v in model.process_vintages[r, p, t] |
663 | 668 | } |
| 669 | + |
| 670 | + |
| 671 | +def gather_group_active_processes( |
| 672 | + model: TemoaModel, r: Region, p: Period, t: Technology |
| 673 | +) -> set[tuple[Region, Technology]]: |
| 674 | + """ |
| 675 | + A utility to get the valid active processes for a group-region, tech-group pair in period p. |
| 676 | + Caches the result if its a new call so we don't repeat these O(n2) lookups. |
| 677 | + """ |
| 678 | + if (r, p, t) not in model.group_active_processes: |
| 679 | + model.group_active_processes[r, p, t] = { |
| 680 | + (_r, _t) |
| 681 | + for _r in geography.gather_group_regions(model, r) |
| 682 | + for _t in technology.gather_group_techs(model, t) |
| 683 | + if (_r, p, _t) in model.process_vintages |
| 684 | + } |
| 685 | + return model.group_active_processes[r, p, t] |
| 686 | + |
| 687 | + |
| 688 | +def gather_group_built_processes( |
| 689 | + model: TemoaModel, r: Region, t: Technology, v: Vintage |
| 690 | +) -> set[tuple[Region, Technology]]: |
| 691 | + """ |
| 692 | + A utility to get the valid built processes for a group-region, tech-group, vintage index. |
| 693 | + Caches the result if its a new call so we don't repeat these O(n2) lookups. |
| 694 | + """ |
| 695 | + if (r, t, v) not in model.group_built_processes: |
| 696 | + model.group_built_processes[r, t, v] = { |
| 697 | + (_r, _t) |
| 698 | + for _r in geography.gather_group_regions(model, r) |
| 699 | + for _t in technology.gather_group_techs(model, t) |
| 700 | + if (_r, _t, v) in model.process_periods |
| 701 | + } |
| 702 | + return model.group_built_processes[r, t, v] |
0 commit comments