Skip to content
Draft
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1d810a8
Simplify EnergySystem class
p-snft Jan 29, 2025
0a012c0
Move test_views from init file to regular file
p-snft Jan 30, 2025
0e0f81a
Always create EnergySystem.tsa_parameters
p-snft Jan 30, 2025
0cfa002
Clean periods from Model and Flow class
p-snft Jan 30, 2025
4f4dcfd
Remove Multi-Period optimisation from InvestFlows
p-snft Feb 24, 2025
0665fe7
Adhere to Black
p-snft Feb 24, 2025
09e4618
Rename InvestmentFlowBlock.invest to .added_capacity
p-snft Feb 25, 2025
362ec01
Delete _extract_multi_period_model_result from processing
p-snft Feb 25, 2025
63b214f
Introduce placeholder for multi-period investment
p-snft Feb 26, 2025
1901a83
Update "PERIOD_INDEXES" constant in processing
p-snft Feb 26, 2025
3974781
Make tsam example consistent
p-snft Feb 26, 2025
b6665b5
Do not return empty "scalars" in result dict
p-snft Feb 26, 2025
c5dee34
Simplyfiy debugging of Flow tests
p-snft Feb 26, 2025
641b56d
Merge branch 'dev' into revision/simplify_indexes
p-snft Feb 26, 2025
7277caf
Let views check if scalars exist
p-snft Feb 26, 2025
c0bef32
Set correct number of time steps for non-time-aggregated model
p-snft Feb 26, 2025
9a01b37
Start adjusting storage to new scheme
p-snft Feb 26, 2025
d37d200
Adhere to Black
p-snft Feb 26, 2025
8f349cb
Revert renaming invest to added_capacity
p-snft Feb 27, 2025
32e880c
Fix length of non-TSA model
p-snft Feb 27, 2025
0eb1d29
Delete outdated multi-period tests
p-snft Feb 27, 2025
41f8490
Fix import order
p-snft Feb 28, 2025
e5ce613
Fix SimpleFlow tests
p-snft Feb 28, 2025
735070c
Merge branch 'dev' into revision/simplify_indexes
p-snft Mar 10, 2025
2057018
Always give scalars in result processing
p-snft Mar 10, 2025
14b8d7a
Remove remains of multi-period-mode from GenericStorage
p-snft Mar 10, 2025
adf55bb
Merge branch 'dev' into revision/simplify_indexes
p-snft Mar 10, 2025
b922383
Collect storage investment results
p-snft Mar 10, 2025
b4f3753
Merge branch 'dev' into revision/simplify_indexes
p-snft Mar 25, 2025
c3277f8
Rename INVESTMENT_PERIODS to CAPACITY_PERIODS
p-snft Mar 25, 2025
a60ed11
Allow empty initialisation of EnergySystem
p-snft Mar 25, 2025
2a2048e
Rename test_outputlib/test_processing.py
p-snft Mar 25, 2025
6faf4fd
Fix file docstring
p-snft Mar 25, 2025
166c3bc
Adhere to Black
p-snft Mar 25, 2025
5f8f9f0
Move TSA "tests" to examples
p-snft Apr 1, 2025
6261c60
Move calculation of TSA occurences to model
p-snft Apr 1, 2025
8502eef
Fix variable_costs wrongly considered
p-snft Apr 1, 2025
54a9590
Fix model tests
p-snft Apr 1, 2025
bd771b8
Rename storage content variables
p-snft Apr 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions examples/basic_example/basic_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,8 @@


def get_data_from_file_path(file_path: str) -> pd.DataFrame:
try:
data = pd.read_csv(file_path)
except FileNotFoundError:
dir = os.path.dirname(os.path.abspath(__file__))
data = pd.read_csv(dir + "/" + file_path)
dir = os.path.dirname(os.path.abspath(__file__))
data = pd.read_csv(dir + "/" + file_path)
return data


Expand Down Expand Up @@ -118,7 +115,7 @@ def main(dump_and_restore=False):

solver = "cbc" # 'glpk', 'gurobi',....
debug = False # Set number_of_timesteps to 3 to get a readable lp-file.
number_of_time_steps = len(data)
number_of_time_steps = 24 # len(data)
solver_verbose = False # show/hide solver output

# initiate the logger (see the API docs for more information)
Expand Down
138 changes: 41 additions & 97 deletions examples/tsam/invest_optimize_all_technologies_using_mp_and_tsam.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
The example describes the use of time series aggregation
methods for seasonal storages in oemof. For this the package tsam is used
for this purpose, which is developed by Forschungszentrum Jülich. For a more detailed
explanation we refer to the paper "Time series aggregation for energy
for this purpose, which is developed by Forschungszentrum Jülich. For a more
detailed explanation we refer to the paper "Time series aggregation for energy
system design: Modeling seasonal storage" by Kotzur et. al.
https://www.sciencedirect.com/science/article/pii/S0306261918300242
Expand Down Expand Up @@ -110,11 +110,8 @@
{"pv": [0.3, 0.5], "wind": [0.6, 0.8], "demand_el": [500, 600]}
)

data = pd.concat([data, data], ignore_index=True)
data["wind"].iloc[8760 - 24 : 8760] = 0
data["wind"].iloc[8760 * 2 - 24 : 8760] = 0
data["pv"].iloc[8760 - 24 : 8760] = 0
data["pv"].iloc[8760 * 2 - 24 : 8760] = 0
data.iloc["wind", 8760 - 24 : 8760] = 0
data.iloc["pv", 8760 - 24 : 8760] = 0

##########################################################################
# Initialize the energy system and read/calculate necessary parameters
Expand All @@ -124,10 +121,8 @@
logging.info("Initialize the energy system")

t1 = pd.date_range("2022-01-01", periods=8760, freq="h")
t2 = pd.date_range("2033-01-01", periods=8760, freq="h")
tindex = t1.append(t2)

data.index = tindex
data.index = t1
del data["timestep"]

typical_periods = 40
Expand All @@ -144,44 +139,15 @@
addPeakMin=["wind", "pv"],
representationMethod="durationRepresentation",
)

aggregation1.createTypicalPeriods()
aggregation2 = tsam.TimeSeriesAggregation(
timeSeries=data.iloc[8760:],
noTypicalPeriods=typical_periods,
hoursPerPeriod=hours_per_period,
clusterMethod="hierarchical",
sortValues=False,
rescaleClusterPeriods=False,
extremePeriodMethod="replace_cluster_center",
addPeakMin=["wind", "pv"],
representationMethod="durationRepresentation",
)
aggregation2.createTypicalPeriods()

t1_agg = pd.date_range(
"2022-01-01", periods=typical_periods * hours_per_period, freq="H"
"2022-01-01", periods=typical_periods * hours_per_period, freq="h"
)
t2_agg = pd.date_range(
"2033-01-01", periods=typical_periods * hours_per_period, freq="H"
)
tindex_agg = t1_agg.append(t2_agg)

energysystem = solph.EnergySystem(
timeindex=tindex_agg,
timeincrement=[1] * len(tindex_agg),
periods=[t1_agg, t2_agg],
tsa_parameters=[
{
"timesteps_per_period": aggregation1.hoursPerPeriod,
"order": aggregation1.clusterOrder,
"timeindex": aggregation1.timeIndex,
},
{
"timesteps_per_period": aggregation2.hoursPerPeriod,
"order": aggregation2.clusterOrder,
"timeindex": aggregation2.timeIndex,
},
],
timeindex=aggregation1,
infer_last_interval=False,
)

Expand Down Expand Up @@ -216,49 +182,26 @@
label="rgas", outputs={bgas: solph.Flow(variable_costs=price_gas)}
)

wind_profile = pd.concat(
[
aggregation1.typicalPeriods["wind"],
aggregation2.typicalPeriods["wind"],
],
ignore_index=True,
)
wind_profile.iloc[-24:] = 0
wind_profile = aggregation1.typicalPeriods["wind"]

# create fixed source object representing wind power plants
wind = solph.components.Source(
label="wind",
outputs={
bel: solph.Flow(
fix=wind_profile,
nominal_capacity=solph.Investment(
ep_costs=epc_wind, lifetime=10
),
nominal_capacity=solph.Investment(ep_costs=epc_wind),
)
},
)

pv_profile = pd.concat(
[aggregation1.typicalPeriods["pv"], aggregation2.typicalPeriods["pv"]],
ignore_index=True,
)
pv_profile.iloc[-24:] = 0

# create fixed source object representing pv power plants
pv = solph.components.Source(
label="pv",
outputs={
bel: solph.Flow(
fix=pd.concat(
[
aggregation1.typicalPeriods["pv"],
aggregation2.typicalPeriods["pv"],
],
ignore_index=True,
),
nominal_capacity=solph.Investment(
ep_costs=epc_pv, lifetime=10
),
fix=aggregation1.typicalPeriods["pv"],
nominal_capacity=solph.Investment(ep_costs=epc_pv),
)
},
)
Expand All @@ -268,13 +211,7 @@
label="demand",
inputs={
bel: solph.Flow(
fix=pd.concat(
[
aggregation1.typicalPeriods["demand_el"],
aggregation2.typicalPeriods["demand_el"],
],
ignore_index=True,
),
fix=aggregation1.typicalPeriods["demand_el"],
nominal_value=1,
)
},
Expand All @@ -288,22 +225,28 @@
conversion_factors={bel: 0.58},
)

# create storage object representing a battery
storage = solph.components.GenericStorage(
label="storage",
inputs={bel: solph.Flow(variable_costs=0.0001)},
outputs={bel: solph.Flow()},
loss_rate=0.01,
lifetime_inflow=10,
lifetime_outflow=10,
invest_relation_input_capacity=1 / 6,
invest_relation_output_capacity=1 / 6,
inflow_conversion_factor=1,
outflow_conversion_factor=0.8,
nominal_capacity=solph.Investment(ep_costs=epc_storage, lifetime=10),
)
energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas)

storage = None
if True:

Check warning

Code scanning / CodeQL

Constant in conditional expression or statement Warning

Testing a constant will always give the same result.
# create storage object representing a battery
storage = solph.components.GenericStorage(
label="storage",
inputs={bel: solph.Flow(variable_costs=0.0001)},
outputs={bel: solph.Flow()},
loss_rate=0.01,
lifetime_inflow=10,
lifetime_outflow=10,
invest_relation_input_capacity=1 / 6,
invest_relation_output_capacity=1 / 6,
inflow_conversion_factor=1,
outflow_conversion_factor=0.8,
nominal_capacity=solph.Investment(
ep_costs=epc_storage, lifetime=10
),
)

energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas, storage)
energysystem.add(storage)

##########################################################################
# Optimise the energy system
Expand Down Expand Up @@ -339,16 +282,17 @@
meta_results = solph.processing.meta_results(om)
pp.pprint(meta_results)

my_results = electricity_bus["period_scalars"]
my_results = electricity_bus["scalars"]

# installed capacity of storage in GWh
my_results["storage_invest_GWh"] = (
results[(storage, None)]["period_scalars"]["invest"] / 1e6
)
if storage:
# installed capacity of storage in GWh
my_results["storage_invest_GWh"] = (
results[(storage, None)]["scalars"]["invest"] / 1e6
)

# installed capacity of wind power plant in MW
my_results["wind_invest_MW"] = (
results[(wind, bel)]["period_scalars"]["invest"] / 1e3
results[(wind, bel)]["scalars"]["capacity"] / 1e3
)

# resulting renewable energy share
Expand Down
Loading
Loading