Breakthrough-Energy / SwitchWrapper

Wrapper for Switch
MIT License
1 stars 2 forks source link

ValueError: No value for uninitialized NumericValue object #83

Open danielolsen opened 3 years ago

danielolsen commented 3 years ago

:beetle:

Bug summary

When running a Switch model using the code currently in the mvp branch, the solver finds an optimal solution, and writes outputs to a pickle file, but then throws a ValueError.

Code for reproduction

Preparation:

import os

import pandas as pd
from powersimdata import Scenario

from switchwrapper.prepare import prepare_inputs

scenario = Scenario(599)
grid = scenario.get_grid()
profiles = {
    "demand": scenario.get_demand(),
    "hydro": scenario.get_hydro(),
    "solar": scenario.get_solar(),
    "wind": scenario.get_wind(),
}
timepoints = pd.read_csv("timepoints_input_v2.csv", index_col=0)
timestamps_to_timepoints = pd.read_csv("slicing_recovery.csv", index_col=0).squeeze()
prepare_inputs(grid, profiles, timepoints, timestamps_to_timepoints, os.path.join("prepared", "inputs"))

Launching:

solve --verbose --solver gurobi --suffixes dual

Actual outcome

The output produced by the above code, which may be a screenshot, console output, etc.

solve --verbose --solver gurobi --suffixes dual

=======================================================================
Switch 2.0.6, http://switch-model.org
=======================================================================
Arguments:
logs_dir='logs', inputs_dir='inputs', suffixes=['dual'], solver='gurobi', solver_manager='serial', outputs_dir='outputs', verbose=True
Modules:
switch_model, switch_model.timescales, switch_model.financials, switch_model.balancing.load_zones, switch_model.energy_sources.properties, switch_model.generators.core.build, switch_model.generators.core.dispatch, switch_model.generators.core.no_commit, switch_model.energy_sources.fuel_costs.simple, switch_model.transmission.local_td, switch_model.transmission.transport.build, switch_model.transmission.transport.dispatch, switch_model.reporting, switch_model.solve
=======================================================================

Model created in 0.24 s.
Loading inputs...
Data read in 3.67 s.

Instance created from data in 161.02 s.

Total time spent constructing model: 164.69 s.

Solving model...
Solved model. Total time spent in solver: 140.247918 s.

Optimization termination condition was optimal.
Solver message: Model was solved to optimality (subject to tolerances), and an optimal solution is available.

Saved results in 22.09 s.
Executing post solve functions...
ERROR: evaluating object as numeric value: BuildTx[88607ac,2030]
        (object: <class 'pyomo.core.base.var._GeneralVarData'>)
    No value for uninitialized NumericValue object BuildTx[88607ac,2030]
ERROR: evaluating object as numeric value: TxCapacityNameplate[88607ac,2030]
        (object: <class 'pyomo.core.base.expression._GeneralExpressionData'>)
    No value for uninitialized NumericValue object BuildTx[88607ac,2030]
Traceback (most recent call last):
  File "/home/dolsen/.local/bin/switch", line 8, in <module>
    sys.exit(main())
  File "/home/dolsen/.local/lib/python3.8/site-packages/switch_model/main.py", line 39, in main
    main()
  File "/home/dolsen/.local/lib/python3.8/site-packages/switch_model/solve.py", line 183, in main
    instance.post_solve()
  File "/home/dolsen/.local/lib/python3.8/site-packages/switch_model/utilities.py", line 252, in post_solve
    module.post_solve(instance, outputs_dir)
  File "/home/dolsen/.local/lib/python3.8/site-packages/switch_model/transmission/transport/build.py", line 336, in post_solve
    normalized_dat = [
  File "/home/dolsen/.local/lib/python3.8/site-packages/switch_model/transmission/transport/build.py", line 346, in <listcomp>
    "TxCapacityNameplate": value(mod.TxCapacityNameplate[tx,p]),
  File "/home/dolsen/.local/lib/python3.8/site-packages/pyomo/core/expr/numvalue.py", line 226, in value
    tmp = obj(exception=True)
  File "/home/dolsen/.local/lib/python3.8/site-packages/pyomo/core/base/expression.py", line 54, in __call__
    return self.expr(exception=exception)
  File "/home/dolsen/.local/lib/python3.8/site-packages/pyomo/core/expr/numeric_expr.py", line 223, in __call__
    return evaluate_expression(self, exception)
  File "/home/dolsen/.local/lib/python3.8/site-packages/pyomo/core/expr/visitor.py", line 974, in evaluate_expression
    return visitor.dfs_postorder_stack(exp)
  File "/home/dolsen/.local/lib/python3.8/site-packages/pyomo/core/expr/visitor.py", line 519, in dfs_postorder_stack
    flag, value = self.visiting_potential_leaf(_sub)
  File "/home/dolsen/.local/lib/python3.8/site-packages/pyomo/core/expr/visitor.py", line 894, in visiting_potential_leaf
    return True, value(node)
  File "/home/dolsen/.local/lib/python3.8/site-packages/pyomo/core/expr/numvalue.py", line 228, in value
    raise ValueError(
ValueError: No value for uninitialized NumericValue object BuildTx[88607ac,2030]

Expected outcome

No error.

Environment

Please specify your platform and versions of the relevant libraries you are using:

YifanLi86 commented 3 years ago

image

Parallel transmission line issue. Remove the other two parallel lines you will see the error pops up for some other parallel branches. Remove all parallel lines you will not see this error again anymore. It is an issue with SWITCH's post processing code.

danielolsen commented 3 years ago

Interesting. Perhaps Switch generates the outputs for BuildTx based on looking up branches by their to/from pairs, and because of this it generates outputs for branch 88606 (the first of the parallel), but none of the others. For the purposes of running Switch successfully all the way through, perhaps we should combine all parallel branches when we generate the inputs.

rouille commented 3 years ago

@danielolsen, if we do that, should we then also keep the expanded grid this way? The we can keep the power flow as it is, i.e, we don't have to decompose the value since we will have always one line between two buses.

danielolsen commented 3 years ago

@danielolsen, if we do that, should we then also keep the expanded grid this way? The we can keep the power flow as it is, i.e, we don't have to decompose the value since we will have always one line between two buses.

I would say that it depends on what we want to use the expanded grid for. If we want to run it through a PCM, maybe we don't want to lose the information about the parallel paths. There would also be implications for reliability analyses, one big branch vs. several smaller ones makes a difference.

rouille commented 3 years ago

@danielolsen, if we do that, should we then also keep the expanded grid this way? The we can keep the power flow as it is, i.e, we don't have to decompose the value since we will have always one line between two buses.

I would say that it depends on what we want to use the expanded grid for. If we want to run it through a PCM, maybe we don't want to lose the information about the parallel paths. There would also be implications for reliability analyses, one big branch vs. several smaller ones makes a difference.

We would just combine the parallel lines into the grid_to_switch module then. In that case we could save the information to later quickly decompose the power flow.