Skip to content

Commit 0fe1bdd

Browse files
committed
Merge branch 'drop_timeslice' into demand_path
2 parents 1d5aec2 + c4de33b commit 0fe1bdd

15 files changed

Lines changed: 87 additions & 90 deletions

docs/inputs/technodata.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ TechnicalLife
112112
represents the number of years that a technology operates before it is decommissioned.
113113

114114
UtilizationFactor
115-
represents the maximum actual output of the technology in a year, divided by the theoretical maximum output if the technology were operating at full capacity for the whole year. Must be between 0 and 1.
115+
represents the *maximum* actual output of the technology in a year, divided by the theoretical maximum output if the technology were operating at full capacity for the whole year. Must be between 0 and 1.
116+
117+
MinimumServiceFactor
118+
Is the *minimum* output of the technology in a year, divided by the theoretical maximum output if the technology were operating at full capacity for the whole year. Must be between 0 and 1 and be smaller or equal than the `UtilizationFactor`. It is used to define the minimum service level that a technology must provide due to, typically, technical or efficiency constraints.
116119

117120
ScalingSize
118121
represents the reference capacity at which capital costs are estimated when used as agents' objective as described in :ref:`inputs-agents`.

src/muse/agents/agent.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import xarray as xr
88

9+
from muse.timeslices import drop_timeslice
10+
911

1012
class AbstractAgent(ABC):
1113
"""Base class for all agents."""
@@ -416,7 +418,7 @@ def next(
416418
return None
417419

418420
if "timeslice" in search.dims:
419-
search["demand"] = demand.drop_vars(["timeslice", "month", "day", "hour"])
421+
search["demand"] = drop_timeslice(demand)
420422
else:
421423
search["demand"] = demand
422424
not_assets = [u for u in search.demand.dims if u != "asset"]

src/muse/constraints.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def constraints(
115115
from mypy_extensions import KwArg
116116

117117
from muse.registration import registrator
118+
from muse.timeslices import drop_timeslice
118119

119120
CAPACITY_DIMS = "asset", "replacement", "region"
120121
"""Default dimensions for capacity decision variables."""
@@ -530,7 +531,7 @@ def minimum_service(
530531
.drop_vars("technology")
531532
)
532533
capacity = convert_timeslice(
533-
techs.fixed_outputs * techs.utilization_factor * techs.minimum_service_factor,
534+
techs.fixed_outputs * techs.minimum_service_factor,
534535
market.timeslice,
535536
QuantityType.EXTENSIVE,
536537
)
@@ -622,7 +623,7 @@ def lp_costs(
622623
production = zeros_like(ts_costs * fouts)
623624
for dim in production.dims:
624625
if isinstance(production.get_index(dim), pd.MultiIndex):
625-
production = production.drop_vars(["timeslice", "month", "day", "hour"])
626+
production = drop_timeslice(production)
626627
production[dim] = pd.Index(production.get_index(dim), tupleize_cols=False)
627628

628629
return xr.Dataset(dict(capacity=costs, production=production))
@@ -689,7 +690,7 @@ def lp_constraint(constraint: Constraint, lpcosts: xr.Dataset) -> Constraint:
689690
constraint = constraint.copy(deep=False)
690691
for dim in constraint.dims:
691692
if isinstance(constraint.get_index(dim), pd.MultiIndex):
692-
constraint = constraint.drop_vars(["timeslice", "month", "day", "hour"])
693+
constraint = drop_timeslice(constraint)
693694
constraint[dim] = pd.Index(constraint.get_index(dim), tupleize_cols=False)
694695
b = constraint.b.drop_vars(set(constraint.b.coords) - set(constraint.b.dims))
695696
b = b.rename({k: f"c({k})" for k in b.dims})

src/muse/demand_matching.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import pandas as pd
5252
from xarray import DataArray
5353

54+
from muse.timeslices import drop_timeslice
55+
5456

5557
def demand_matching(
5658
demand: DataArray,
@@ -248,7 +250,7 @@ def demand_matching(
248250

249251
if len(multics) > 0:
250252
for k in multics:
251-
ds = ds.drop_vars(["timeslice", "month", "day", "hour"])
253+
ds = drop_timeslice(ds)
252254
ds[k] = pd.Index(constraint.get_index(k), tupleize_cols=False)
253255
result = demand_matching( # type: ignore
254256
ds.demand, ds.cost, *(ds[f"constraint{i}"] for i in range(len(constraints)))

src/muse/examples.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
from muse.mca import MCA
3636
from muse.sectors import AbstractSector
37+
from muse.timeslices import drop_timeslice
3738

3839
__all__ = ["model", "technodata"]
3940

@@ -192,12 +193,8 @@ def mca_market(model: str = "default") -> xr.Dataset:
192193
.sel(region=settings.regions)
193194
.interp(year=settings.time_framework, method=settings.interpolation_mode)
194195
)
195-
market["supply"] = zeros_like(market.exports).drop_vars(
196-
["timeslice", "month", "day", "hour"]
197-
)
198-
market["consumption"] = zeros_like(market.exports).drop_vars(
199-
["timeslice", "month", "day", "hour"]
200-
)
196+
market["supply"] = drop_timeslice(zeros_like(market.exports))
197+
market["consumption"] = drop_timeslice(zeros_like(market.exports))
201198

202199
return cast(xr.Dataset, market)
203200

@@ -263,12 +260,12 @@ def matching_market(sector: str, model: str = "default") -> xr.Dataset:
263260
market = market.rename(dst_region="region")
264261
if market.region.dims:
265262
consump = consumption(loaded_sector.technologies, production)
266-
market["consumption"] = (
263+
market["consumption"] = drop_timeslice(
267264
consump.groupby("region").sum(
268265
{"asset", "dst_region"}.intersection(consump.dims)
269266
)
270267
+ market.supply
271-
).drop_vars(["timeslice", "month", "day", "hour"])
268+
)
272269
else:
273270
market["consumption"] = (
274271
consumption(loaded_sector.technologies, production).sum(

src/muse/mca.py

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from muse.outputs.cache import OutputCache
1515
from muse.readers import read_initial_market
1616
from muse.sectors import SECTORS_REGISTERED, AbstractSector
17+
from muse.timeslices import drop_timeslice
1718

1819

1920
class MCA:
@@ -59,12 +60,8 @@ def factory(cls, settings: str | Path | Mapping | Any) -> MCA:
5960
).sel(region=settings.regions)
6061
).interp(year=settings.time_framework, method=settings.interpolation_mode)
6162

62-
market["supply"] = zeros_like(market.exports).drop_vars(
63-
["timeslice", "month", "day", "hour"]
64-
)
65-
market["consumption"] = zeros_like(market.exports).drop_vars(
66-
["timeslice", "month", "day", "hour"]
67-
)
63+
market["supply"] = drop_timeslice(zeros_like(market.exports))
64+
market["consumption"] = drop_timeslice(zeros_like(market.exports))
6865

6966
# We create the sectors
7067
sectors = []
@@ -461,9 +458,7 @@ def single_year_iteration(
461458
sectors = deepcopy(sectors)
462459
market = market.copy(deep=True)
463460
if "updated_prices" not in market.data_vars:
464-
market["updated_prices"] = market.prices.copy().drop_vars(
465-
["timeslice", "month", "day", "hour"]
466-
)
461+
market["updated_prices"] = drop_timeslice(market.prices.copy())
467462

468463
# eventually, the first market should be one that creates the initial demand
469464
for sector in sectors:
@@ -551,16 +546,12 @@ def find_equilibrium(
551546
else:
552547
included = ones(len(market.commodity), dtype=bool)
553548

554-
market["updated_prices"] = market.prices.copy().drop_vars(
555-
["timeslice", "month", "day", "hour"]
556-
)
549+
market["updated_prices"] = drop_timeslice(market.prices.copy())
557550
prior_market = market.copy(deep=True)
558551
converged = False
559552
equilibrium_sectors = sectors
560553
for i in range(maxiter):
561-
market["prices"] = market.updated_prices.drop_vars(
562-
["timeslice", "month", "day", "hour"]
563-
)
554+
market["prices"] = drop_timeslice(market.updated_prices)
564555
prior_market, market = market, prior_market
565556
market.consumption[:] = 0.0
566557
market.supply[:] = 0.0
@@ -582,9 +573,11 @@ def find_equilibrium(
582573
new_price.loc[dict(commodity=included)] = market.updated_prices.sel(
583574
commodity=included, year=market.year[1]
584575
)
585-
market["prices"] = future_propagation( # type: ignore
586-
market["prices"], new_price
587-
).drop_vars(["timeslice", "month", "day", "hour"])
576+
market["prices"] = drop_timeslice(
577+
future_propagation( # type: ignore
578+
market["prices"], new_price
579+
)
580+
)
588581

589582
break
590583

@@ -599,9 +592,11 @@ def find_equilibrium(
599592
dict(year=market.year[1], commodity=included)
600593
]
601594
)
602-
market["prices"] = future_propagation( # type: ignore
603-
market["prices"], new_price
604-
).drop_vars(["timeslice", "month", "day", "hour"])
595+
market["prices"] = drop_timeslice(
596+
future_propagation( # type: ignore
597+
market["prices"], new_price
598+
)
599+
)
605600
if not equilibrium:
606601
equilibrium_reached = True
607602
converged = True
@@ -626,9 +621,11 @@ def find_equilibrium(
626621
0.2
627622
* market.updated_prices.loc[dict(year=market.year[1], commodity=included)]
628623
)
629-
market["prices"] = future_propagation( # type: ignore
630-
market["prices"], new_price
631-
).drop_vars(["timeslice", "month", "day", "hour"])
624+
market["prices"] = drop_timeslice(
625+
future_propagation( # type: ignore
626+
market["prices"], new_price
627+
)
628+
)
632629
getLogger(__name__).critical(msg)
633630

634631
return FindEquilibriumResults(

src/muse/objectives.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ def comfort(
8181
from muse.agents import Agent
8282
from muse.outputs.cache import cache_quantity
8383
from muse.registration import registrator
84+
from muse.timeslices import drop_timeslice
8485

8586
OBJECTIVE_SIGNATURE = Callable[
8687
[Agent, xr.DataArray, xr.DataArray, xr.Dataset, xr.Dataset, KwArg(Any)],
@@ -142,7 +143,7 @@ def objectives(
142143
for name, objective in functions:
143144
obj = objective(agent, demand, search_space, *args, **kwargs)
144145
if "timeslice" in obj.dims and "timeslice" in result.dims:
145-
obj = obj.drop_vars(["timeslice", "month", "day", "hour"])
146+
obj = drop_timeslice(obj)
146147
result[name] = obj
147148
return result
148149

src/muse/outputs/mca.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def quantity(
3434

3535
from muse.registration import registrator
3636
from muse.sectors import AbstractSector
37-
from muse.timeslices import QuantityType, convert_timeslice
37+
from muse.timeslices import QuantityType, convert_timeslice, drop_timeslice
3838

3939
OUTPUT_QUANTITY_SIGNATURE = Callable[
4040
[xr.Dataset, list[AbstractSector], KwArg(Any)], Union[xr.DataArray, pd.DataFrame]
@@ -362,9 +362,9 @@ def sector_supply(sector: AbstractSector, market: xr.Dataset, **kwargs) -> pd.Da
362362
capacity = a.filter_input(a.assets.capacity, year=output_year).fillna(0.0)
363363
technologies = a.filter_input(techs, year=output_year).fillna(0.0)
364364
agent_market = market.sel(year=output_year).copy()
365-
agent_market["consumption"] = (
365+
agent_market["consumption"] = drop_timeslice(
366366
agent_market.consumption * a.quantity
367-
).drop_vars(["timeslice", "month", "day", "hour"])
367+
)
368368
included = [
369369
i
370370
for i in agent_market["commodity"].values
@@ -607,9 +607,9 @@ def sector_consumption(
607607
capacity = a.filter_input(a.assets.capacity, year=output_year).fillna(0.0)
608608
technologies = a.filter_input(techs, year=output_year).fillna(0.0)
609609
agent_market = market.sel(year=output_year).copy()
610-
agent_market["consumption"] = (
610+
agent_market["consumption"] = drop_timeslice(
611611
agent_market.consumption * a.quantity
612-
).drop_vars(["timeslice", "month", "day", "hour"])
612+
)
613613
included = [
614614
i
615615
for i in agent_market["commodity"].values

src/muse/sectors/preset_sector.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from xarray import DataArray, Dataset
88

99
from muse.sectors.register import AbstractSector, register_sector
10+
from muse.timeslices import drop_timeslice
1011

1112

1213
@register_sector(name=("preset", "presets"))
@@ -77,15 +78,15 @@ def factory(cls, name: str, settings: Any) -> PresetSector:
7778
assert consumption.region.isin(shares.region).all()
7879
if "timeslice" in shares.dims:
7980
ts = shares.timeslice
80-
shares = shares.drop_vars(["timeslice", "month", "day", "hour"])
81+
shares = drop_timeslice(shares)
8182
consumption = (shares * consumption).assign_coords(timeslice=ts)
8283
else:
8384
consumption = consumption * shares.sel(
8485
region=consumption.region, commodity=consumption.commodity
8586
)
86-
presets["consumption"] = consumption.drop_vars(
87-
["timeslice", "month", "day", "hour"]
88-
).assign_coords(timeslice=timeslice)
87+
presets["consumption"] = drop_timeslice(consumption).assign_coords(
88+
timeslice=timeslice
89+
)
8990

9091
if getattr(sector_conf, "supply_path", None) is not None:
9192
supply = read_csv_outputs(sector_conf.supply_path)
@@ -115,9 +116,7 @@ def factory(cls, name: str, settings: Any) -> PresetSector:
115116
for component in components:
116117
others = components.intersection(presets.data_vars).difference({component})
117118
if component not in presets and len(others) > 0:
118-
presets[component] = zeros_like(presets[others.pop()]).drop_vars(
119-
["timeslice", "month", "day", "hour"], errors="ignore"
120-
)
119+
presets[component] = drop_timeslice(zeros_like(presets[others.pop()]))
121120
# add timeslice, if missing
122121
for component in {"supply", "consumption"}:
123122
if "timeslice" not in presets[component].dims:
@@ -166,9 +165,9 @@ def next(self, mca_market: Dataset) -> Dataset:
166165
mca_market.timeslice,
167166
QuantityType.EXTENSIVE,
168167
)
169-
result["costs"] = convert_timeslice(
170-
costs, mca_market.timeslice, QuantityType.INTENSIVE
171-
).drop_vars(["timeslice", "month", "day", "hour"], errors="ignore")
168+
result["costs"] = drop_timeslice(
169+
convert_timeslice(costs, mca_market.timeslice, QuantityType.INTENSIVE)
170+
)
172171
assert isinstance(result, Dataset)
173172
return result
174173

src/muse/sectors/subsector.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import xarray as xr
1212

1313
from muse.agents import Agent
14+
from muse.timeslices import drop_timeslice
1415

1516

1617
class Subsector:
@@ -57,9 +58,9 @@ def invest(
5758
current_year = market.year.min()
5859
if self.expand_market_prices:
5960
market = market.copy()
60-
market["prices"] = np.maximum(
61-
market.prices, market.prices.rename(region="dst_region")
62-
).drop_vars(["timeslice", "month", "day", "hour"])
61+
market["prices"] = drop_timeslice(
62+
np.maximum(market.prices, market.prices.rename(region="dst_region"))
63+
)
6364

6465
for agent in self.agents:
6566
agent.asset_housekeeping()

0 commit comments

Comments
 (0)