refactor: introduce FeasibilitySolver and StreamDistributionItem - #1457
Conversation
8765f65 to
ee5465e
Compare
| self, | ||
| inlet_stream: FluidStream, | ||
| items: dict[T, HasCapacity], | ||
| items: dict[T, HasExcessRate], |
There was a problem hiding this comment.
I was thinking CommonStreamDistribution would use FeasibilitySolver directly, so passing target_pressure in addition. Not sure if that matters much, but it would remove the HasExcessRate interface which might be a bit confusing. It's unclear that excess rate depends on target pressure in that interface.
There was a problem hiding this comment.
I see your point about clarity. However, if we remove the StreamDistributionItem (HasValidity, HasExcessCapacity), CommonStreamDistribution needs to keep track of two dictionaries (feasibility solvers, target pressures) - and I guess tests will be "heavier" (need to build OutletPressureSolver, ProcessRunner, compressors etc.). Another thing is that PrioritiesStreamDistribution is using HasValidity. Without StreamDistributionItem I assume PrioritiesStreamDistribution also needs to take feasibility solvers and target pressures.
Can it be an alternative to have a clearer docstring in the HasExcessRate interface, to clarify the target pressure dependency?
Summary
Introduces
FeasibilitySolverto calculate how much rate exceeds a compressor train's capacity, and connects it to stream distribution via a thinStreamDistributionItemadapter. RenamesHasCapacitytoHasExcessRatewith aFluidStream-based interface.Architecture
Three layers with distinct responsibilities:
FeasibilitySolverOutletPressureSolverand queries compressor stone walls.domain/process/process_solver/StreamDistributionItemFeasibilitySolverto a fixedtarget_pressureand implementsHasExcessRate+HasValidity.presentation/yaml/mappers/HasExcessRate(wasHasCapacity)CommonStreamDistributionto query overflow. Now takes aFluidStreaminstead of(rate, pressure).domain/process/stream_distribution/What changed
New:
FeasibilitySolver(process_solver/feasibility_solver.py)get_excess_rate(inlet_stream, target_pressure) → floatOutletPressureSolver.find_solution(). If the solver succeeds, excess is 0. If it fails, applies the failed solution's configuration and finds the bottleneck compressor's stone wall limit.New:
StreamDistributionItem(presentation/yaml/mappers/process_simulation_mapper.py)HasExcessRateandHasValiditytarget_pressureso stream distribution interfaces only need aninlet_streamis_valid(stream)=get_excess_rate(stream) == 0.0Renamed:
HasCapacity→HasExcessRateget_unhandled_rate(rate, pressure)→get_excess_rate(inlet_stream: FluidStream)Usage
PrioritiesStreamDistributioncallsitem.is_valid(stream)to pick the first feasible setting.CommonStreamDistributioncallsitem.get_excess_rate(stream)to route overflow between trains.Refs:
equinor/ecalc-internal#1634
equinor/ecalc-internal#1635
Type of Work
See here (internal): https://github.com/equinor/ecalc-internal/discussions/1044
Have you remembered and considered?
docs/drafts/next.draft.md)docs/docs/migration_guides/)BREAKING:in footer or!in headerWhat is this PR all about?
What else did you consider?
Between the lines?