Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix storage sub components name #273

Merged
merged 3 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading