public void CanSolveMaxProblem() { var problem = new EquationSystem(); var x1 = new Variable("x1", 10); problem.AddVariables(x1); problem.AddConstraints((Sym.Max(x1, 5)).IsEqualTo(25)); var solver = new Newton(); solver.Solve(problem); Assert.AreEqual(25, x1.ValueInSI, 1e-5); Assert.AreEqual(true, solver.IsConverged); }
public void Test_MinMax() { var x = new Variable { Name = "x", ValueInSI = 3 }; var y = new Variable { Name = "y", ValueInSI = 6 }; var eval = new Evaluator(); Assert.AreEqual(3, Sym.Min(x, y).Eval(eval), 1e-5); Assert.AreEqual(6, Sym.Max(x, y).Eval(eval), 1e-5); }
public void CanSolveMinMaxProblem() { var problem = new EquationSystem(); var x1 = new Variable("x1", 0); var x2 = new Variable("x2", 6); var x3 = new Variable("x3", 25); problem.AddVariables(x2); problem.AddConstraints((Sym.Max(x1, Sym.Min(x2, x3))).IsEqualTo(5)); var solver = new Newton(); solver.Solve(problem); Assert.AreEqual(5, x2.ValueInSI, 1e-5); Assert.AreEqual(true, solver.IsConverged); }
/// <summary> /// Creates a new instance of the liquid phase activity coefficient calculation object /// </summary> /// <param name="sys">Thermodynamic system to take parameters from</param> /// <param name="T">Temperature variable</param> /// <param name="x">Vector of composition variables (molar fractions)</param> /// <param name="idx">Index of the active variables to calculate for</param> public ActivityCoefficientUNIQUAC(ThermodynamicSystem sys, Variable T, List <Variable> x, int idx) { Symbol = "UNIQUAC_GAMMA"; _system = sys; index = idx; //Bind variables to this instance this.T = T; this.x = x; Parameters.Add(T); foreach (var comp in x) { Parameters.Add(comp); } NC = _system.Components.Count; tau = new Expression[NC, NC]; int i = index; var parameterSet = _system.BinaryParameters.FirstOrDefault(ps => ps.Name == "UNIQUAC"); if (parameterSet == null) { throw new ArgumentNullException("No UNIQUAC parameters defined"); } double[,] a = parameterSet.Matrices["A"]; double[,] b = parameterSet.Matrices["B"]; double[,] c = parameterSet.Matrices["C"]; double[,] d = parameterSet.Matrices["D"]; double[,] e = parameterSet.Matrices["E"]; for (int ii = 0; ii < NC; ii++) { for (int j = 0; j < NC; j++) { tau[ii, j] = Sym.Exp(a[ii, j] + b[ii, j] / T + c[ii, j] * Sym.Ln(T) + d[ii, j] * T + e[ii, j] / Sym.Pow(T, 2)); } } Expression lnGamma = 0.0; Expression lnGammaComb = 0.0; Expression lnGammaRes = 0.0; Expression Vi = 0; Expression Fi = 0; Expression FiP = 0; Expression Sxl = 0; var ri = _system.Components.Select(co => co.GetParameter(MethodTypes.Uniquac, "R").ValueInSI).ToList(); var qi = _system.Components.Select(co => co.GetParameter(MethodTypes.Uniquac, "Q").ValueInSI).ToList(); var qpi = _system.Components.Select(co => co.GetParameter(MethodTypes.Uniquac, "Q'").ValueInSI).ToList(); double[] li = new double[NC]; for (int j = 0; j < NC; j++) { li[j] = 5 * (ri[j] - qi[j]) - (ri[j] - 1); } Vi = ri[i] * x[i] / Sym.Sum(0, NC, (j) => ri[j] * x[j]); Fi = qi[i] * x[i] / Sym.Sum(0, NC, (j) => qi[j] * x[j]); FiP = qpi[i] * x[i] / Sym.Sum(0, NC, (j) => qpi[j] * x[j]); //Sxl = Sym.Sum(0, NC, (j) => (5 * (_system.Components[j].GetParameter(MethodTypes.Uniquac, "R").ValueInSI - _system.Components[j].GetParameter(MethodTypes.Uniquac, "Q").ValueInSI) - (_system.Components[j].GetParameter(MethodTypes.Uniquac, "R").ValueInSI - 1)) * x[j]); lnGammaComb = Sym.Ln(Vi / Sym.Max(1e-10, x[i])) + 5 * qi[i] * Sym.Ln(Fi / Vi) + li[i] - Vi / Sym.Max(1e-10, x[i]) * Sym.Sum(0, NC, j => x[j] * li[j]); Expression[] FPj = new Expression[_system.Components.Count]; for (int j = 0; j < NC; j++) { FPj[j] = qpi[j] * x[j] / Sym.Sum(0, NC, (kj) => qpi[kj] * x[kj]); } var doubleSum = Sym.Sum(0, NC, (j) => FPj[j] * tau[i, j] / (Sym.Sum(0, NC, (k) => FPj[k] * tau[k, j]))); var SFP = Sym.Sum(0, NC, (j) => FPj[j] * tau[j, i]); lnGammaRes = qpi[i] * (1.0 - Sym.Ln(SFP) - doubleSum); lnGamma = lnGammaComb + lnGammaRes; _gamma_exp = Sym.Exp(lnGamma); _dgamma_dx = new Expression[NC]; DiffFunctional = (cache, v) => _gamma_exp.Diff(cache, v); EvalFunctional = (cache) => _gamma_exp.Eval(cache); }
public override void FillEquationSystem(EquationSystem problem) { int NC = System.Components.Count; var vliq = Sym.Sum(0, NC, i => Liquid.ComponentMolarflow[i] * Liquid.ComponentMolarVolume[i]); var vvap = Vapor.TotalMolarflow / Vapor.DensityMolar; MW.BindTo(System.EquationFactory.GetAverageMolarWeightExpression(System, Mixed.ComponentMolarFraction.ToArray())); Liquid.TotalVolumeflow.BindTo(vliq); Vapor.TotalVolumeflow.BindTo(vvap); Mixed.TotalVolumeflow.BindTo(vliq + vvap); Mixed.TotalMassflow.BindTo(Sym.Sum(Mixed.ComponentMassflow)); Liquid.TotalMassflow.BindTo(Sym.Sum(Liquid.ComponentMassflow)); Vapor.TotalMassflow.BindTo(Sym.Sum(Vapor.ComponentMassflow)); //Liquid.SpecificEnthalpy.BindTo(Sym.Par(Sym.Sum(0, NC, (idx) => Liquid.ComponentMolarFraction[idx] * Liquid.ComponentEnthalpy[idx]))); //Vapor.SpecificEnthalpy.BindTo(Sym.Par(Sym.Sum(0, NC, (idx) => Vapor.ComponentMolarFraction[idx] * Vapor.ComponentEnthalpy[idx]))); Liquid.SpecificEnthalpy.BindTo(new EnthalpyRoute(System, Mixed.Temperature, Mixed.Pressure, Liquid.ComponentMolarFraction, PhaseState.Liquid)); Vapor.SpecificEnthalpy.BindTo(new EnthalpyRoute(System, Mixed.Temperature, Mixed.Pressure, Vapor.ComponentMolarFraction, PhaseState.Vapour)); Mixed.Density.BindTo(Mixed.TotalMassflow / Mixed.TotalVolumeflow); Liquid.Density.BindTo(Liquid.TotalMassflow / Liquid.TotalVolumeflow); Vapor.Density.BindTo(Vapor.TotalMassflow / Vapor.TotalVolumeflow); Mixed.DensityMolar.BindTo(Mixed.TotalMolarflow / Mixed.TotalVolumeflow); Liquid.DensityMolar.BindTo(Liquid.TotalMolarflow / Liquid.TotalVolumeflow); Vapor.DensityMolar.BindTo(System.EquationFactory.GetAverageVaporDensityExpression(System, Mixed.Temperature, Mixed.Pressure, Vapor.ComponentMolarFraction)); for (int i = 0; i < NC; i++) { Mixed.ComponentMassflow[i].BindTo(Mixed.ComponentMolarflow[i] * Sym.Convert(System.Components[i].GetConstant(ConstantProperties.MolarWeight), SI.kg / SI.mol)); Mixed.ComponentMassFraction[i].BindTo(Mixed.ComponentMassflow[i] / Sym.Max(1e-12, Mixed.TotalMassflow)); Liquid.ComponentMassflow[i].BindTo(Liquid.ComponentMolarflow[i] * Sym.Convert(System.Components[i].GetConstant(ConstantProperties.MolarWeight), SI.kg / SI.mol)); Liquid.ComponentMassFraction[i].BindTo(Liquid.ComponentMassflow[i] / Sym.Max(1e-12, Liquid.TotalMassflow)); Liquid.ComponentMolarVolume[i].BindTo((1.0 / System.EquationFactory.GetLiquidDensityExpression(System, System.Components[i], Mixed.Temperature, Mixed.Pressure))); Liquid.ComponentEnthalpy[i].BindTo(System.EquationFactory.GetLiquidEnthalpyExpression(System, i, Mixed.Temperature)); Vapor.ComponentMassflow[i].BindTo(Vapor.ComponentMolarflow[i] * Sym.Convert(System.Components[i].GetConstant(ConstantProperties.MolarWeight), SI.kg / SI.mol)); Vapor.ComponentMassFraction[i].BindTo(Vapor.ComponentMassflow[i] / Sym.Max(1e-12, Vapor.TotalMassflow)); Vapor.ComponentEnthalpy[i].BindTo(System.EquationFactory.GetVaporEnthalpyExpression(System, i, Mixed.Temperature)); } Mixed.TotalEnthalpy.BindTo(((Mixed.TotalMolarflow * Mixed.SpecificEnthalpy))); Liquid.TotalEnthalpy.BindTo(((Liquid.TotalMolarflow * Liquid.SpecificEnthalpy))); Vapor.TotalEnthalpy.BindTo(((Vapor.TotalMolarflow * Vapor.SpecificEnthalpy))); if (!Mixed.SpecificEnthalpy.IsFixed) { Mixed.SpecificEnthalpy.BindTo((Sym.Par(Vapor.TotalMolarflow * Vapor.SpecificEnthalpy + Liquid.TotalMolarflow * Liquid.SpecificEnthalpy) / Mixed.TotalMolarflow)); } else { AddEquationToEquationSystem(problem, (Mixed.SpecificEnthalpy * Mixed.TotalMolarflow).IsEqualTo(Vapor.TotalMolarflow * Vapor.SpecificEnthalpy + Liquid.TotalMolarflow * Liquid.SpecificEnthalpy), "Enthalpy Balance"); } AddEquationToEquationSystem(problem, Mixed.TotalMolarflow.IsEqualTo(Sym.Sum(Mixed.ComponentMolarflow)), "Mass Balance"); for (int i = 0; i < NC; i++) { // AddEquationToEquationSystem(problem, (Mixed.ComponentMolarFraction[i] * Mixed.TotalMolarflow).IsEqualTo(Liquid.ComponentMolarFraction[i] * Liquid.TotalMolarflow + Vapor.ComponentMolarFraction[i] * Vapor.TotalMolarflow)); AddEquationToEquationSystem(problem, (Mixed.ComponentMolarflow[i]).IsEqualTo(Liquid.ComponentMolarflow[i] + Vapor.ComponentMolarflow[i])); // Mixed.ComponentMolarflow[i].BindTo(Liquid.ComponentMolarflow[i] + Vapor.ComponentMolarflow[i]); } for (int i = 0; i < NC; i++) { AddEquationToEquationSystem(problem, (Mixed.ComponentMolarFraction[i] * Mixed.TotalMolarflow).IsEqualTo(Mixed.ComponentMolarflow[i])); //Mixed.ComponentMolarFraction[i].BindTo(Mixed.ComponentMolarflow[i]/ Mixed.TotalMolarflow); } for (int i = 0; i < NC; i++) { AddEquationToEquationSystem(problem, (Liquid.ComponentMolarFraction[i] * Liquid.TotalMolarflow).IsEqualTo(Liquid.ComponentMolarflow[i])); //Liquid.ComponentMolarFraction[i].BindTo(Liquid.ComponentMolarflow[i] / Sym.Max(1e-12, Liquid.TotalMolarflow)); } for (int i = 0; i < NC; i++) { AddEquationToEquationSystem(problem, (Vapor.ComponentMolarFraction[i] * Vapor.TotalMolarflow).IsEqualTo(Vapor.ComponentMolarflow[i])); // Vapor.ComponentMolarFraction[i].BindTo(Vapor.ComponentMolarflow[i] / Sym.Max(1e-12, Vapor.TotalMolarflow)); } AddEquationToEquationSystem(problem, (Vfmolar * Mixed.TotalMolarflow).IsEqualTo((Vapor.TotalMolarflow)), "Vapor Fraction"); switch (State) { case PhaseState.BubblePoint: AddEquationToEquationSystem(problem, (Sym.Sum(Liquid.ComponentMolarFraction) - Sym.Sum(Vapor.ComponentMolarFraction)).IsEqualTo(Beta), "Equilibrium"); AddEquationToEquationSystem(problem, Beta.IsEqualTo(0), "Equilibrium"); AddEquationToEquationSystem(problem, Liquid.TotalMolarflow.IsEqualTo(Sym.Sum(Liquid.ComponentMolarflow)), "Mass Balance"); break; case PhaseState.DewPoint: AddEquationToEquationSystem(problem, (Sym.Sum(Liquid.ComponentMolarFraction) - Sym.Sum(Vapor.ComponentMolarFraction)).IsEqualTo(Beta), "Equilibrium"); AddEquationToEquationSystem(problem, Beta.IsEqualTo(0), "Equilibrium"); AddEquationToEquationSystem(problem, Vapor.TotalMolarflow.IsEqualTo(Sym.Sum(Vapor.ComponentMolarflow)), "Mass Balance"); break; default: if (Vfmolar.IsFixed) { AddEquationToEquationSystem(problem, (Sym.Sum(Liquid.ComponentMolarFraction) - Sym.Sum(Vapor.ComponentMolarFraction)).IsEqualTo(Beta), "Equilibrium"); AddEquationToEquationSystem(problem, Beta.IsEqualTo(0), "Equilibrium"); } else { AddEquationToEquationSystem(problem, (Sym.Sum(Liquid.ComponentMolarFraction) - Sym.Sum(Vapor.ComponentMolarFraction)).IsEqualTo(Beta), "Equilibrium"); AddEquationToEquationSystem(problem, Sym.Mid(Vfmolar, Beta, Vfmolar - 1).IsEqualTo(0), "Equilibrium"); } AddEquationToEquationSystem(problem, (Mixed.TotalMolarflow).IsEqualTo(Vapor.TotalMolarflow + Liquid.TotalMolarflow), "Mass Balance"); break; } for (int i = 0; i < NC; i++) { System.EquationFactory.EquilibriumCoefficient(System, KValues[i], Mixed.Temperature, Mixed.Pressure, Liquid.ComponentMolarFraction, Vapor.ComponentMolarFraction, i); AddEquationToEquationSystem(problem, Vapor.ComponentMolarFraction[i].IsEqualTo(KValues[i] * Liquid.ComponentMolarFraction[i]), "Equilibrium"); } base.FillEquationSystem(problem); }