Skip to content

Commit

Permalink
Merge pull request #273 from open-plan-tool/fix/storage-sub-component…
Browse files Browse the repository at this point in the history
…s-name

Fix storage sub components name
  • Loading branch information
Bachibouzouk authored Sep 16, 2024
2 parents 410ddb6 + 1b426ac commit 6550b43
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 118 deletions.
38 changes: 28 additions & 10 deletions app/dashboard/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1368,7 +1368,8 @@ def graph_costs(
return simulations_results


def graph_sankey(simulation, energy_vector):
def graph_sankey(simulation, energy_vector, timestep=None):
ts = timestep
if isinstance(energy_vector, list) is False:
energy_vector = [energy_vector]
if energy_vector is not None:
Expand All @@ -1395,9 +1396,14 @@ def graph_sankey(simulation, energy_vector):
labels.append(bus_label)
colors.append("blue")

asset_to_bus_names = qs.filter(bus=bus.name, direction="in").values_list(
"asset", "total_flow"
)
if ts is None:
asset_to_bus_names = qs.filter(
bus=bus.name, direction="in"
).values_list("asset", "total_flow")
else:
asset_to_bus_names = qs.filter(
bus=bus.name, direction="in"
).values_list("asset", "flow_data")

for component_label, val in asset_to_bus_names:
# draw link from the component to the bus
Expand All @@ -1408,17 +1414,25 @@ def graph_sankey(simulation, energy_vector):
sources.append(labels.index(component_label))
targets.append(labels.index(bus_label))

if ts is not None:
val = json.loads(val)
val = val[ts]

if component_label in chp_in_flow:
chp_in_flow[component_label]["value"] += val

if val == 0:
val = 1e-6

val = 1e-9
values.append(val)
if ts is None:
bus_to_asset_names = qs.filter(
bus=bus.name, direction="out"
).values_list("asset", "total_flow")
else:
bus_to_asset_names = qs.filter(
bus=bus.name, direction="out"
).values_list("asset", "flow_data")

bus_to_asset_names = qs.filter(bus=bus.name, direction="out").values_list(
"asset", "total_flow"
)
# TODO potentially rename feedin period and consumption period
for component_label, val in bus_to_asset_names:
# draw link from the bus to the component
Expand All @@ -1432,8 +1446,12 @@ def graph_sankey(simulation, energy_vector):
if component_label in chp_in_flow:
chp_in_flow[component_label]["bus"] = bus_label

if ts is not None:
val = json.loads(val)
val = val[ts]

if val == 0:
val = 1e-6
val = 1e-9
values.append(val)

# TODO display the installed capacity, max capacity and optimized_add_capacity on the nodes if applicable
Expand Down
5 changes: 5 additions & 0 deletions app/dashboard/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@
scenario_visualize_sankey,
name="scenario_visualize_sankey",
),
re_path(
r"^scenario/results/request_sankey/(?P<scen_id>\d+)?(/(?P<ts>\d+))?$",
scenario_visualize_sankey,
name="scenario_visualize_sankey",
),
re_path(
r"^project/(?P<proj_id>\d+)/scenario/results/request-capacities/(?P<scen_id>\d+)?$",
scenario_visualize_capacities,
Expand Down
216 changes: 111 additions & 105 deletions app/dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,13 @@ def scenario_visualize_results(request, proj_id=None, scen_id=None):

topology_data_list = load_scenario_topology_from_db(scen_id)

timestamps = scenario.get_timestamps()
answer = render(
request,
"report/single_scenario.html",
{
"scen_id": scen_id,
"timestamps": timestamps,
"proj_id": proj_id,
"project_list": user_projects,
"scenario_list": user_scenarios,
Expand Down Expand Up @@ -705,7 +707,7 @@ def view_asset_parameters(request, scen_id, asset_type_name, asset_uuid):
form = BusForm(
asset_type=asset_type_name, instance=existing_bus, view_only=True
)

existing_asset = None
context = {"form": form}
elif asset_type_name in ["bess", "h2ess", "gess", "hess"]:
template = "asset/storage_asset_create_form.html"
Expand Down Expand Up @@ -765,125 +767,126 @@ def view_asset_parameters(request, scen_id, asset_type_name, asset_uuid):
}
)

# fetch optimized capacity and flow if they exist
qs = FancyResults.objects.filter(simulation=scenario.simulation)
if existing_asset is not None:
# fetch optimized capacity and flow if they exist
qs = FancyResults.objects.filter(simulation=scenario.simulation)

if qs.exists():
qs_fine = qs.exclude(asset__contains="@").filter(
asset__contains=existing_asset.name
)
negative_direction = "out"
if existing_asset.is_storage is True and optimized_cap is True:
for cap in qs_fine.values_list("optimized_capacity", flat=True):
context.update(
{"optimized_add_cap": {"value": round(cap, 2), "unit": "kWh"}}
)
if qs.exists():
qs_fine = qs.exclude(asset__contains="@").filter(
asset__contains=existing_asset.name
)
negative_direction = "out"
if existing_asset.is_storage is True and optimized_cap is True:
for cap in qs_fine.values_list("optimized_capacity", flat=True):
context.update(
{"optimized_add_cap": {"value": round(cap, 2), "unit": "kWh"}}
)

elif existing_asset.is_provider is True:
negative_direction = "in"
else:
qs_fine = qs_fine.filter(asset=existing_asset.name)
elif existing_asset.is_provider is True:
negative_direction = "in"
else:
qs_fine = qs_fine.filter(asset=existing_asset.name)

traces = []
total_flows = []
timestamps = scenario.get_timestamps(json_format=True)
traces = []
total_flows = []
timestamps = scenario.get_timestamps(json_format=True)

if len(qs_fine) == 1:
asset_results = qs_fine.get()
total_flows.append(
{
"value": round(asset_results.total_flow, 2),
"unit": "kWh",
"label": "",
}
)
if existing_asset.optimize_cap is True:
context.update(
if len(qs_fine) == 1:
asset_results = qs_fine.get()
total_flows.append(
{
"optimized_add_cap": {
"value": round(asset_results.optimized_capacity, 2),
"unit": "kW",
"value": round(asset_results.total_flow, 2),
"unit": "kWh",
"label": "",
}
)
if existing_asset.optimize_cap is True:
context.update(
{
"optimized_add_cap": {
"value": round(asset_results.optimized_capacity, 2),
"unit": "kW",
}
}
)
traces.append(
{
"value": json.loads(asset_results.flow_data),
"name": existing_asset.name,
"unit": "kW",
}
)
traces.append(
{
"value": json.loads(asset_results.flow_data),
"name": existing_asset.name,
"unit": "kW",
}
)
else:
else:

qs_fine = qs_fine.annotate(
name=Case(
When(
Q(asset_type__contains="chp") & Q(direction="in"),
then=Concat("asset", Value(" out ("), "bus", Value(")")),
qs_fine = qs_fine.annotate(
name=Case(
When(
Q(asset_type__contains="chp") & Q(direction="in"),
then=Concat("asset", Value(" out ("), "bus", Value(")")),
),
When(
Q(asset_type__contains="chp") & Q(direction="out"),
then=Concat("asset", Value(" in")),
),
When(
Q(asset_type__contains="ess") & Q(direction="in"),
then=Concat("asset", Value(" " + _("Discharge"))),
),
When(
Q(asset_type__contains="ess") & Q(direction="out"),
then=Concat("asset", Value(" " + _("Charge"))),
),
When(
Q(oemof_type="transformer") & Q(direction="out"),
then=Concat("asset", Value(" in")),
),
When(
Q(oemof_type="transformer") & Q(direction="in"),
then=Concat("asset", Value(" out")),
),
default=F("asset"),
),
When(
Q(asset_type__contains="chp") & Q(direction="out"),
then=Concat("asset", Value(" in")),
unit=Case(
When(Q(asset_type__contains="ess"), then=Value("kWh")),
default=Value("kW"),
),
When(
Q(asset_type__contains="ess") & Q(direction="in"),
then=Concat("asset", Value(" " + _("Discharge"))),
),
When(
Q(asset_type__contains="ess") & Q(direction="out"),
then=Concat("asset", Value(" " + _("Charge"))),
),
When(
Q(oemof_type="transformer") & Q(direction="out"),
then=Concat("asset", Value(" in")),
),
When(
Q(oemof_type="transformer") & Q(direction="in"),
then=Concat("asset", Value(" out")),
),
default=F("asset"),
),
unit=Case(
When(Q(asset_type__contains="ess"), then=Value("kWh")),
default=Value("kW"),
),
value=F("flow_data"),
)

for y_vals in qs_fine.order_by("direction").values(
"name", "value", "unit", "direction", "total_flow"
):
# make consumption values negative other wise inflow of asset is negative
if y_vals["direction"] == negative_direction:
y_vals["value"] = (
-1 * np.array(json.loads(y_vals["value"]))
).tolist()
else:
y_vals["value"] = json.loads(y_vals["value"])
value=F("flow_data"),
)

traces.append(y_vals)
for y_vals in qs_fine.order_by("direction").values(
"name", "value", "unit", "direction", "total_flow"
):
# make consumption values negative other wise inflow of asset is negative
if y_vals["direction"] == negative_direction:
y_vals["value"] = (
-1 * np.array(json.loads(y_vals["value"]))
).tolist()
else:
y_vals["value"] = json.loads(y_vals["value"])

total_flows.append(
{
"value": round(y_vals["total_flow"], 2),
"unit": y_vals["unit"],
"label": y_vals["name"],
}
)
traces.append(y_vals)

if existing_asset.is_provider is True:
# add the possibility to see the cap limit on the feedin on the result graph
feedin_cap = existing_asset.feedin_cap
if feedin_cap is not None:
traces.append(
total_flows.append(
{
"value": [feedin_cap for t in timestamps],
"name": parameters_helper.get_doc_verbose("feedin_cap"),
"unit": parameters_helper.get_doc_unit("feedin_cap"),
"options": {"visible": "legendonly"},
"value": round(y_vals["total_flow"], 2),
"unit": y_vals["unit"],
"label": y_vals["name"],
}
)

if existing_asset.is_provider is True:
# add the possibility to see the cap limit on the feedin on the result graph
feedin_cap = existing_asset.feedin_cap
if feedin_cap is not None:
traces.append(
{
"value": [feedin_cap for t in timestamps],
"name": parameters_helper.get_doc_verbose("feedin_cap"),
"unit": parameters_helper.get_doc_unit("feedin_cap"),
"options": {"visible": "legendonly"},
}
)

context.update(
{
"form": form,
Expand Down Expand Up @@ -1116,18 +1119,21 @@ def scenario_visualize_costs(request, proj_id, scen_id=None):


# TODO: Sector coupling must be refined (including transformer flows)
def scenario_visualize_sankey(request, scen_id):
def scenario_visualize_sankey(request, scen_id, ts=None):
scenario = get_object_or_404(Scenario, pk=scen_id)
if (scenario.project.user != request.user) and (
scenario.project.viewers.filter(user__email=request.user.email).exists()
is False
):
raise PermissionDenied

if ts is not None:
ts = int(ts)
results_json = report_item_render_to_json(
report_item_id="sankey",
data=REPORT_GRAPHS[GRAPH_SANKEY](
simulation=scenario.simulation, energy_vector=scenario.energy_vectors
simulation=scenario.simulation,
energy_vector=scenario.energy_vectors,
timestep=ts,
),
title="Sankey",
report_item_type=GRAPH_SANKEY,
Expand Down
4 changes: 4 additions & 0 deletions app/projects/scenario_topology_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,13 @@ def handle_storage_unit_form_post(
new_name = form.cleaned_data.pop("name", None)
if new_name is not None:
ess_asset.name = new_name
ess_capacity_asset.name = f"{ess_asset.name} capacity"
ess_charging_power_asset.name = f"{ess_asset.name} input power"
ess_discharging_power_asset.name = f"{ess_asset.name} output power"
ess_asset.save()
else:
# Create the ESS Parent Asset

ess_asset = Asset.objects.create(
name=form.cleaned_data.pop("name"),
asset_type=get_object_or_404(
Expand Down
Loading

0 comments on commit 6550b43

Please sign in to comment.