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

Allocation: optimize per source #1927

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open

Conversation

SouthEndMusic
Copy link
Collaborator

@SouthEndMusic SouthEndMusic commented Nov 4, 2024

Optimizing per source

Fixes #565

What happens now in optimizing per subnetwork per priority (see optimize_priority!):

  • set_capacities_flow_demand_outflow!: Set the capacity of outflow edge of a node with a flow demand (Inf if priority == flow demand priority, 0 otherwise)
  • set_objective_priority!: Set the equal ratio objective function (a term per demand of the current priority)
  • allocate_to_users_from_connected_basin!: Do allocation without optimization where users are directly connected to basins that can supply flow
  • allocate_priority!: solve the optimization problem
  • assign_allocations!: copy the allocated values to the proper places (either for UserDemand or a subnetwork treated as a UserDemand node)
  • save_demands_and_allocations!: Write allocation result data to the allocation record (record_demand) for the allocation.arrow output
  • save_allocation_flows!: Write allocation flow data to the allocation record (record_flow) for the allocation_flow.arrow output

What has to change when optimizing per source:

  • Add vector of sources in subnetwork in desired order to AllocationModel struct and add this to AllocationModel constructor in allocation_init.jl. Types of sources (in order used for now, 'use flow available within subnetwork first'): edge designated as source, basin with level demand, main network to subnetwork, connector node with flow demand (buffer)
  • Add loop over sources in allocate_priority!
  • Within this loop, set the capacity of the current source as the capacity of this source and the other sources 0, after which the optimization is run
  • Adapt all adjust_* functions for use within this loop and make sure flow_priority is cumulative over all sources
  • Call save_demands_and_allocarions! and save_allocation_flows! after the loop
  • Adjust the allocation docs to solving per source (both allocation.qmd instances)

Limiting flow demand buffer inflow

Fixes #1504
Fixes #1709 (hopefully)

A bit of background here: nodes that have a flow demand have a flow buffer, which is implemented so that if the flow that goes from a source to a node with a flow demand has nowhere to go afterwards, it can be stored in the flow buffer to potentially be allocated downstream in subsequent optimizations.

Currently the flow into the flow buffer is unconstrained, meaning that for each optimization an arbitrary amount of flow can end up in the buffer. The objective only cares about the flow over the edge into the node with the flow demand, not about the flow into the buffer. Changes:

  • Remove flow demand outflow 0 or Inf constraints
  • Use buffer inflow instead of flow to node with flow demand in objective function
  • Flow that goes through the flow demand node but not into the buffer should still count towards what's allocated to the flow demand
  • Fix tests
  • Update inline docs
  • Update online docs (both allocation.qmd instances)

@SouthEndMusic SouthEndMusic self-assigned this Nov 4, 2024
@SouthEndMusic SouthEndMusic changed the title nits Allocation: optimize per source Nov 4, 2024
@SouthEndMusic SouthEndMusic marked this pull request as draft November 4, 2024 14:09
@SouthEndMusic
Copy link
Collaborator Author

Note (@visr @gijsber): this PR changes (again) how UserDemand returnflow (and flow buffers) is used as a source. Previously, when some flow was allocated to a UserDemand node, the return flow fraction was available as a source for the next priority (also to the same UserDemand node if the graph topology permits). Now that we optimize per source, when some flow is allocated to a UserDemand node from one source, the return fraction is already available as a source when optimizing for the next source within the same priority. We could go back to the same behavior as before but that requires some extra book keeping.

@gijsber
Copy link
Contributor

gijsber commented Nov 6, 2024

Hi @SouthEndMusic , I prefer the new behaviour. The old behaviour did not have my preference but seemed like unavoidable at that time.

@SouthEndMusic
Copy link
Collaborator Author

Another point of attention: I think I already assumed this before, but I will rely on it now/again: for flow demands only flows in the direction of the edge count, not the other way. I think this is a reasonable assumption and requires less complexity

@SouthEndMusic
Copy link
Collaborator Author

Maintaining the allocation developer docs seems a bit of a chore, especially with the call stacks in place in combination with inline documentation. @FaridAlavi, I'd be interested to hear what you think the value of this documentation page is from your perspective.

@SouthEndMusic SouthEndMusic marked this pull request as ready for review November 12, 2024 15:25
@SouthEndMusic
Copy link
Collaborator Author

Apart from get_sources_in_order the changes to allocation_init.jl are minor. The changes to allocation_optim.jl are more interesting:

Before
allocation_optim_before

After
cell-6-output-1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants