Open
Description
Summary
I was running a model with the new solver writers ("ipopt_v2") and found a case where the model would solve without the linear presolve but raised an exception about too few degrees of freedom if the presolve was turned on.
Steps to reproduce the issue
from pyomo.environ import ConcreteModel, Constraint, Expression, log10, Param, Set, SolverFactory, value, Var
from idaes.core.util.math import smooth_min
def build_model():
m = ConcreteModel()
# Smoothing parameter for complementarities
m.eps = Param(default=1e-3)
m.liquid_products = Set(initialize=["K", "HCO3", "CO3", "Cl", "H2O", "OH-"])
m.solid_products = Set(initialize=["KHCO3", "K2CO3.1.5H2O", "KCl", "K2CO3.2KHCO3.1.5H2O"])
m.feed_species = Set(initialize=["H2O", "KHCO3", "K2CO3", "Cl"])
m.feed_flows = Var(m.feed_species, initialize=0)
m.concentration = Var(m.liquid_products, initialize=0, bounds=(0, None))
m.solid_flows = Var(m.solid_products, initialize=0, bounds=(0, None))
m.pH = Var(initialize=10, bounds=(0, 15))
# Material balances
m.k_balance = Constraint(
expr=m.feed_flows["KHCO3"]
+ 2*m.feed_flows["K2CO3"]
== m.solid_flows["KHCO3"]
+ 2*m.solid_flows["K2CO3.1.5H2O"]
+ m.solid_flows["KCl"]
+ 4*m.solid_flows["K2CO3.2KHCO3.1.5H2O"]
+ m.concentration["K"]
)
m.cl_balance = Constraint(
expr=m.feed_flows["Cl"]
== m.solid_flows["KCl"]
+ m.concentration["Cl"]
)
m.c_balance = Constraint(
expr=m.feed_flows["KHCO3"]
+ m.feed_flows["K2CO3"]
== m.solid_flows["KHCO3"]
+ m.solid_flows["K2CO3.1.5H2O"]
+ 3*m.solid_flows["K2CO3.2KHCO3.1.5H2O"]
+ m.concentration["HCO3"]
+ m.concentration["CO3"]
)
m.o_balance = Constraint(
expr=3*m.feed_flows["KHCO3"]
+ 3*m.feed_flows["K2CO3"]
+ m.feed_flows["H2O"]
== 3*m.solid_flows["KHCO3"]
+ 4.5*m.solid_flows["K2CO3.1.5H2O"]
+ 10.5*m.solid_flows["K2CO3.2KHCO3.1.5H2O"]
+ 3*m.concentration["HCO3"]
+ 3*m.concentration["CO3"]
+ m.concentration["H2O"]
+ m.concentration["OH-"]
)
# pH Constraint
m.pH_constraint = Constraint(expr=14+log10(m.concentration["OH-"]) == m.pH)
# Carbonate equilibrium
m.carbonate_equil = Constraint(expr=1e5*m.concentration["HCO3"]*m.concentration["OH-"]==1e5*3.07e-5*m.concentration["CO3"])
# Reaction Quotients
def rxn_rule(m, j):
if j == "KHCO3":
return 13.29680294 - m.concentration["K"]*m.concentration["HCO3"]
if j == "K2CO3.2KHCO3.1.5H2O":
return 1e-5*234181.2733 - 1e-5*m.concentration["K"]**4*m.concentration["CO3"]*m.concentration["HCO3"]**2
if j == "K2CO3.1.5H2O":
return 1e-3*1432.481319 - 1e-3*m.concentration["K"]**2*m.concentration["CO3"]
if j == "KCl":
return 26.46242932 - m.concentration["K"]*m.concentration["Cl"]
m.Q = Expression(m.solid_products, rule=rxn_rule)
# Complmentarity constraints
def comp_rule(m, j):
if j == "KHCO3":
return 0 == smooth_min(m.Q["KHCO3"], m.solid_flows["KHCO3"], m.eps)
if j == "K2CO3.2KHCO3.1.5H2O":
return 0 == smooth_min(m.Q["K2CO3.2KHCO3.1.5H2O"], m.solid_flows["K2CO3.2KHCO3.1.5H2O"], m.eps)
if j == "K2CO3.1.5H2O":
return 0 == smooth_min(m.Q["K2CO3.1.5H2O"], m.solid_flows["K2CO3.1.5H2O"], m.eps)
if j == "KCl":
return 0 == smooth_min(m.Q["KCl"], m.solid_flows["KCl"], m.eps)
return Constraint.Skip
m.complementarity = Constraint(m.solid_products, rule=comp_rule)
return m
if __name__ == "__main__":
m = build_model()
# Set feed conditions
m.feed_flows["H2O"].fix(55.5081)
m.feed_flows["KHCO3"].fix(5)
m.feed_flows["K2CO3"].fix(7.5)
m.feed_flows["Cl"].fix(0)
m.pH.fix(10.3576)
# Solve model
# If "linear_presolve": False, this will run (if with poor numerics)
solver = SolverFactory("ipopt_v2", writer_config={"linear_presolve": True})
solver.solve(m, tee=True)
Error Message
Ipopt 3.13.2:
******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
Ipopt is released as open source code under the Eclipse Public License (EPL).
For more information visit http://projects.coin-or.org/Ipopt
This version of Ipopt was compiled from source code available at
https://github.com/IDAES/Ipopt as part of the Institute for the Design of
Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE
Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.
This version of Ipopt was compiled using HSL, a collection of Fortran codes
for large-scale scientific computation. All technical papers, sales and
publicity material resulting from use of the HSL codes within IPOPT must
contain the following acknowledgement:
HSL, a collection of Fortran codes for large-scale scientific
computation. See http://www.hsl.rl.ac.uk.
******************************************************************************
This is Ipopt version 3.13.2, running with linear solver ma27.
Number of nonzeros in equality constraint Jacobian...: 31
Number of nonzeros in inequality constraint Jacobian.: 0
Number of nonzeros in Lagrangian Hessian.............: 18
Error in an AMPL evaluation. Run with "halt_on_ampl_error yes" to see details.
Error evaluating Jacobian of equality constraints at user provided starting point.
No scaling factors for equality constraints computed!
Exception of type: TOO_FEW_DOF in file "IpIpoptApplication.cpp" at line 926:
Exception message: status != TOO_FEW_DEGREES_OF_FREEDOM evaluated false: Too few degrees of freedom (rethrown)!
EXIT: Problem has too few degrees of freedom.
Traceback (most recent call last):
File "C:\next_gen_platform\precipitation_test.py", line 107, in <module>
solver.solve(m, tee=True)
~~~~~~~~~~~~^^^^^^^^^^^^^
File "C:\Users\andrew.lee\AppData\Local\miniforge3\envs\workflow_manager\Lib\site-packages\pyomo\contrib\solver\base.py", line 598, in solve
results: Results = super().solve(model)
~~~~~~~~~~~~~^^^^^^^
File "C:\Users\andrew.lee\AppData\Local\miniforge3\envs\workflow_manager\Lib\site-packages\pyomo\contrib\solver\ipopt.py", line 447, in solve
raise RuntimeError(
...<2 lines>...
)
RuntimeError: A feasible solution was not found, so no solution can be loaded.Please set opt.config.load_solutions=False to bypass this error.
Information on your system
Pyomo version: Pyomo 6.8.2
Python version: 3.13.1
Operating system: Windows 11
How Pyomo was installed: clone from source
Solver (if applicable): IDAES distribution of IPOPT