Source code for powersimdata.design.mimic_grid
def _calculate_common_zone_factors(base_plant, ref_plant, plant_scaling, epsilon=1e-3):
"""Given a base plant dataframe, a reference plant dataframe, and a scaling
vector: calculate common zone scaling factors, and produce a change-table
with an equivalent combination of zone and plant scaling factors.
:param pandas.DataFrame base_plant: plant dataframe for base grid.
:param pandas.DataFrame ref_plant: plant dataframe for reference grid.
:param pandas.Series plant_scaling: scaling factors by plant to get from
base_plant Pmax values to ref_plant Pmax values.
:return: (*dict*) -- dictionary of plant/zone scaling factors in a format
matching powersimdata.input.change_table.
"""
change_table = {}
new_plant_scaling = plant_scaling.copy()
# Detect if any zones have all-zero plant scaling (e.g. wind_offshore)
grouping = new_plant_scaling.groupby([base_plant.type, base_plant.zone_id])
total_scale = grouping.sum()
for fuel, zone_id in total_scale.index:
if total_scale.loc[(fuel, zone_id)] == 0:
if fuel not in change_table:
change_table[fuel] = {"zone_id": {}}
change_table[fuel]["zone_id"][zone_id] = 0
# Since we have zone scaling of 0, we don't need plant scaling
matching_indices = grouping.get_group((fuel, zone_id)).index
matching_boolean = new_plant_scaling.index.isin(matching_indices)
new_plant_scaling = new_plant_scaling[~matching_boolean]
# Determine approximately most common non-zero scaling factor via median
nonzero = plant_scaling > 0
grouping = plant_scaling[nonzero].groupby([base_plant.type, base_plant.zone_id])
common_factors = grouping.median()
# Divide plant scaling factors by zone scaling factors as appropriate
for (fuel, zone_id), v in common_factors.to_dict().items():
if fuel not in change_table:
change_table[fuel] = {"zone_id": {}}
if abs(v - 1) <= epsilon:
# Zone scaling not needed if it's close enough to 1
continue
else:
change_table[fuel]["zone_id"][zone_id] = v
# Since we have meaningful zone scaling, modify plant scaling
matching_indices = grouping.get_group((fuel, zone_id)).index
new_plant_scaling.loc[matching_indices] /= v
# Drop plant scaling factors that are nearly 1
approx_1_plants = abs(new_plant_scaling - 1) <= epsilon
new_plant_scaling = new_plant_scaling[~approx_1_plants]
for k, v in new_plant_scaling.to_dict().items():
plantfuel = base_plant.loc[k, "type"]
if plantfuel not in change_table:
change_table[plantfuel] = {}
if "plant_id" not in change_table[plantfuel]:
change_table[plantfuel]["plant_id"] = {}
change_table[plantfuel]["plant_id"][k] = v
return change_table
[docs]def mimic_generation_capacity(base_grid, ref_grid):
"""Given a base grid and a reference grid, determine zone and plant scaling
factors such that the combination, when applied to the base grid, produces
the reference grid.
:param powersimdata.input.grid.Grid base_grid: the base grid (unscaled).
:param powersimdata.input.grid.Grid ref_grid: the base grid (unscaled).
:return: (*dict*) -- dictionary of plant/zone scaling factors in a format
matching ct in powersimdata.input.change_table.ChangeTable.
"""
base_plant = base_grid.plant
ref_plant = ref_grid.plant
plant_scaling = ref_plant.Pmax / base_plant.Pmax
# Element-wise division will return NaN for plants not in ref_grid
plant_scaling = plant_scaling.fillna(0)
change_table = _calculate_common_zone_factors(base_plant, ref_plant, plant_scaling)
return change_table