@BLI thanks for sharing the equations.
Here is how I would get a univariate polynomial in n_H2O_L
that depends on parameters:
using Nemo, Groebner
# 1. Define parameters and variables
_r, (n_H2O, n_1, n_2, V, p_H2O_sat, H_1, H_2, Vt_L, R, T) = Nemo.QQ[:n_H2O, :n_1, :n_2, :V, :p_H2O_sat, :H_1, :H_2, :Vt_L, :R, :T]
_R, (V_L, V_g, n_H2O_L, n_H2O_g, n_1_L, n_2_L, n_1_g, n_2_g, n_L, n_g, p, p_H2O, p_1, p_2, y_H2O, y_1, y_2, x_H2O, x_1, x_2) = fraction_field(_r)[:V_L, :V_g, :n_H2O_L, :n_H2O_g, :n_1_L, :n_2_L, :n_1_g, :n_2_g, :n_L, :n_g, :p, :p_H2O, :p_1, :p_2, :y_H2O, :y_1, :y_2, :x_H2O, :x_1, :x_2]
# 2. Define equations
eq1 = n_H2O_L + n_H2O_g - n_H2O
eq2 = n_1_L + n_1_g - n_1
eq3 = n_2_L + n_2_g - n_2
eq4 = n_H2O_g + n_1_g + n_2_g - n_g
eq5 = n_H2O_L + n_1_L + n_2_L - n_L
eq6 = p_H2O + p_1 + p_2 - p
eq7 = p_H2O*V_g - n_H2O_g*R*T
eq8 = p_1*V_g - n_1_g*R*T
eq9 = p_2*V_g - n_2_g*R*T
eq10 = x_H2O*n_L - n_H2O_L
eq11 = x_1*n_L - n_1_L
eq12 = x_2*n_L - n_2_L
eq13 = y_H2O*n_g - n_H2O_g
eq14 = y_1*n_g - n_1_g
eq15 = y_2*n_g - n_2_g
eq16 = p_H2O - x_H2O*p_H2O_sat
eq17 = p_1 - x_1*H_1
eq18 = p_2 - x_2*H_2
eq19 = V_L - n_H2O_L*Vt_L
eq20 = V_L + V_g - V
eqs_VT_flash = [eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8, eq9, eq10, eq11, eq12, eq13, eq14, eq15, eq16, eq17, eq18, eq19, eq20]
vars_VT_flash = [V_L, V_g, n_H2O_L, n_H2O_g, n_1_L, n_2_L, n_1_g, n_2_g, n_L, n_g, p, p_H2O, p_1, p_2, y_H2O, y_1, y_2, x_H2O, x_1, x_2]
# 3. Make these variables the smallest
interesting_vars = [n_H2O_L]
# 4. Compute a GB, allowing division by parameters
using ParamPunPam
gb = paramgb(
eqs_VT_flash,
# vars > interesting_vars > params
ordering=DegRevLex(setdiff(vars_VT_flash, interesting_vars)) * DegRevLex(interesting_vars)
)
# 5. Inspect. Note: gb[1] is univariate
map(vars, gb)
#= Output
20-element Vector{Vector{AbstractAlgebra.Generic.MPoly{AbstractAlgebra.Generic.FracFieldElem{QQMPolyRingElem}}}}:
[n_H2O_L]
[n_H2O_L, x_2]
[n_H2O_L, x_1]
[n_H2O_L, x_H2O]
[n_H2O_L, y_2]
[n_H2O_L, y_1]
[n_H2O_L, y_H2O]
[n_H2O_L, p_2]
[n_H2O_L, p_1]
[n_H2O_L, p_H2O]
[n_H2O_L, p]
[n_H2O_L, n_g]
[n_H2O_L, n_L]
[n_H2O_L, n_2_g]
[n_H2O_L, n_1_g]
[n_H2O_L, n_2_L]
[n_H2O_L, n_1_L]
[n_H2O_L, n_H2O_g]
[V_g, n_H2O_L]
[V_L, n_H2O_L]
=#
gb[1]
#= Output
n_H2O_L^4 + (n_H2O*p_H2O_sat^2*H_1*Vt_L + n_H2O*p_H2O_sat^2*H_2*Vt_L + n_H2O*p_H2O_sat^2*R*T - 2*n_H2O*p_H2O_sat*H_1*H_2*Vt_L - 2*n_H2O*p_H2O_sat*H_1*R*T - 2*n_H2O*p_H2O_sat*H_2*R*T + 3*n_H2O*H_1*H_2*R*T - n_1*p_H2O_sat^2*R*T + n_1*p_H2O_sat*H_2*R*T - n_2*p_H2O_sat^2*R*T + n_2*p_H2O_sat*H_1*R*T - V*p_H2O_sat^3 + V*p_H2O_sat^2*H_1 + V*p_H2O_sat^2*H_2 - V*p_H2O_sat*H_1*H_2)//(p_H2O_sat^3*Vt_L - p_H2O_sat^2*H_1*Vt_L - p_H2O_sat^2*H_2*Vt_L - p_H2O_sat^2*R*T + p_H2O_sat*H_1*H_2*Vt_L + p_H2O_sat*H_1*R*T + p_H2O_sat*H_2*R*T - H_1*H_2*R*T)*n_H2O_L^3 + (n_H2O^2*p_H2O_sat*H_1*H_2*Vt_L + n_H2O^2*p_H2O_sat*H_1*R*T + n_H2O^2*p_H2O_sat*H_2*R*T - 3*n_H2O^2*H_1*H_2*R*T + n_H2O*n_1*p_H2O_sat^2*R*T - 2*n_H2O*n_1*p_H2O_sat*H_2*R*T + n_H2O*n_2*p_H2O_sat^2*R*T - 2*n_H2O*n_2*p_H2O_sat*H_1*R*T - n_H2O*V*p_H2O_sat^2*H_1 - n_H2O*V*p_H2O_sat^2*H_2 + 2*n_H2O*V*p_H2O_sat*H_1*H_2)//(p_H2O_sat^3*Vt_L - p_H2O_sat^2*H_1*Vt_L - p_H2O_sat^2*H_2*Vt_L - p_H2O_sat^2*R*T + p_H2O_sat*H_1*H_2*Vt_L + p_H2O_sat*H_1*R*T + p_H2O_sat*H_2*R*T - H_1*H_2*R*T)*n_H2O_L^2 + (n_H2O^3*H_1*H_2*R*T + n_H2O^2*n_1*p_H2O_sat*H_2*R*T + n_H2O^2*n_2*p_H2O_sat*H_1*R*T - n_H2O^2*V*p_H2O_sat*H_1*H_2)//(p_H2O_sat^3*Vt_L - p_H2O_sat^2*H_1*Vt_L - p_H2O_sat^2*H_2*Vt_L - p_H2O_sat^2*R*T + p_H2O_sat*H_1*H_2*Vt_L + p_H2O_sat*H_1*R*T + p_H2O_sat*H_2*R*T - H_1*H_2*R*T)*n_H2O_L
=#
Some comments:
- The ordering of indeterminates is: vars > interesting vars > params, + allowing division by params. This can be modeled differently, but I guess this approach works here.
- In 3., mark several variables as interesting to uncover relations between them (for example, [n_H2O_L, n_1_g, n_2_g]).
- I use
ParamPunPam.paramgb
for computing GB, which @nsajko mentioned.
- In 4., swap
paramgb
for groebner
if guaranteed result is needed (paramgb
is probabilistic).
- There are 4 solutions, which agrees with the degree of univariate polynomial:
julia> length(quotient_basis(map(identity, gb)))
4
- From the univariate polynomial, one solution is
n_H2O_L = 0
(I wonder if this has physical meaning).