Search code examples
pythonnumpyscipysolverscipy-optimize

Trouble solving a system of 6 nonlinear equations in Python


I'm trying to solve a system of 6 non linear equations with Python. So far I've got:

from scipy.optimize import fsolve 
import math 
from numpy import log

ka1 = 1.045
ka2 = 0.1759
ka3 = 0.3159

def equations(p):
    yh2o, yco2, yh2, ych4, yco = p

    return (yh2o + yco2 + yh2 + ych4 + yco - 1,
        ka1 - (yh2o ** 2)/(yco * (yh2 ** 2),
        ka2 - (yco ** 2) / yco2,
        ka3 - ych4 / (yh2 ** 2),
        0.5 - (2.0 * yco2 + yco + yh2o) / (2 * yh2o + 2 * yh2 + 4 * ych4)))

yh2o, yco2, yh2, ych4, yco = fsolve(equations, [0.2, 0.2, 0.2, 0.2, 0.2])

print(f"yh2o = {yh2o}, yco2 = {yco2}, yh2 = {yh2}, ych4 = {ych4}, yco = {yco}")

When I try to run this I get

TypeError: fsolve: there is a mismatch between the input and output shape of the 'func' argument 'equations'.Shape should be (5,) but it is (2,).

I've tried changing the initial guess but the error is still the same.

I've also tried changing the equations into polynomials like so:

    return (yh2o + yco2 + yh2 + ych4 + yco - 1.0,
        ka1 * (yco * (yh2 ** 2.0)) - (yh2o * yh2o),
        ka2 * (yco2) - (yco ** 2.0),
        ka3 * (yh2 ** 2.0) - ych4,
        0.5 * (2.0 * yh2o + 2.0 * yh2 + 4 * ych4) - (2.0 * yco2 + yco + yh2o)) 

But I get an error saying

TypeError: can't multiply sequence by non-int of type 'float'

Solution

  • I think you just have problem with parentheses (i.e. placing of ( and )) in your equations (returned tuple).

    Below is full corrected working code:

    Try it online!

    from scipy.optimize import fsolve 
    import math 
    from numpy import log
    
    ka1 = 1.045
    ka2 = 0.1759
    ka3 = 0.3159
    
    def equations(p):
        yh2o, yco2, yh2, ych4, yco = p
    
        return (
            (yh2o + yco2 + yh2 + ych4 + yco - 1),
            ka1 - (yh2o ** 2) / (yco * (yh2 ** 2)),
            ka2 - (yco ** 2) / yco2,
            ka3 - ych4 / (yh2 ** 2),
            0.5 - (2.0 * yco2 + yco + yh2o) / (2 * yh2o + 2 * yh2 + 4 * ych4)
        )
    
    yh2o, yco2, yh2, ych4, yco = fsolve(equations, [0.2, 0.2, 0.2, 0.2, 0.2])
    
    print(f"yh2o = {yh2o}, yco2 = {yco2}, yh2 = {yh2}, ych4 = {ych4}, yco = {yco}")
    

    Output:

    yh2o = 0.17829101808889491, yco2 = 0.17513942402710805, yh2 = 0.4163023675952086, ych4 = 0.05474789024926531, yco = 0.1755193000395232