Beispiel #1
0
        private void Solve()
        {
            //Mass Transfer--material particles transfer from gas stream to liquid stream
            //Mass Transfer--moisture transfers from liquid stream to gas stream
            //by an adiabaitc saturation process if ScrubberType is General.
            DryingMaterialStream dmsInlet  = liquidInlet as DryingMaterialStream;
            DryingMaterialStream dmsOutlet = liquidOutlet as DryingMaterialStream;

            DryingGasStream dgsInlet  = gasInlet as DryingGasStream;
            DryingGasStream dgsOutlet = gasOutlet as DryingGasStream;

            //gas stream goes through an adiabatic saturation process
            double tg1 = dgsInlet.Temperature.Value;
            double y1  = dgsInlet.Humidity.Value;
            double tw1 = dgsInlet.WetBulbTemperature.Value;
            double td1 = dgsInlet.DewPoint.Value;
            double fy1 = dgsInlet.RelativeHumidity.Value;

            double tg2 = dgsOutlet.Temperature.Value;
            double y2  = dgsOutlet.Humidity.Value;
            double tw2 = dgsOutlet.WetBulbTemperature.Value;
            double td2 = dgsOutlet.DewPoint.Value;
            double fy2 = dgsOutlet.RelativeHumidity.Value;

            double ih = 0;
            double p1 = dgsInlet.Pressure.Value;
            double p2 = dgsOutlet.Pressure.Value;

            if (p1 == Constants.NO_VALUE || p2 == Constants.NO_VALUE)
            {
                return;
            }
            HumidGasCalculator humidGasCalculator = GetHumidGasCalculator();

            if (tg1 != Constants.NO_VALUE && y1 != Constants.NO_VALUE)
            {
                ih = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(tg1, y1, p1);
                if (tg2 != Constants.NO_VALUE)
                {
                    y2 = humidGasCalculator.GetHumidityFromHumidEnthalpyTemperatureAndPressure(ih, tg2, p2);
                    if (y2 <= 0.0)
                    {
                        y2 = 1.0e-6;
                    }
                    Calculate(dgsOutlet.MoistureContentDryBase, y2);
                    solveState = SolveState.Solved;
                }
                else if (y2 != Constants.NO_VALUE)
                {
                    tg2 = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(ih, y2, p2);
                    Calculate(dgsOutlet.Temperature, tg2);
                    solveState = SolveState.Solved;
                }
                else if (td2 != Constants.NO_VALUE)
                {
                    y2  = humidGasCalculator.GetHumidityFromDewPointAndPressure(td2, p2);
                    tg2 = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(ih, y2, p2);
                    Calculate(dgsOutlet.Temperature, tg2);
                    solveState = SolveState.Solved;
                }
                else if (fy2 != Constants.NO_VALUE)
                {
                    double fy_temp    = 0;
                    double delta      = 10.0;
                    double totalDelta = delta;
                    tg2 = tg1 - delta;
                    bool negativeLastTime = false;

                    int counter = 0;
                    do
                    {
                        counter++;
                        y2      = humidGasCalculator.GetHumidityFromHumidEnthalpyTemperatureAndPressure(ih, tg2, p2);
                        fy_temp = humidGasCalculator.GetRelativeHumidityFromDryBulbHumidityAndPressure(tg2, y2, p2);
                        if (fy2 > fy_temp)
                        {
                            if (negativeLastTime)
                            {
                                delta /= 2.0; //testing finds delta/2.0 is almost optimal
                            }
                            totalDelta      += delta;
                            negativeLastTime = false;
                        }
                        else if (fy2 < fy_temp)
                        {
                            delta           /= 2.0; //testing finds delta/2.0 is almost optimal
                            totalDelta      -= delta;
                            negativeLastTime = true;
                        }
                        tg2 = tg1 - totalDelta;
                    } while (Math.Abs(fy2 - fy_temp) > 1.0e-6 && counter <= 200);

                    if (counter < 200)
                    {
                        Calculate(dgsOutlet.Temperature, tg2);
                        solveState = SolveState.Solved;
                    }
                }

                if (solveState == SolveState.Solved)
                {
                    double fy = humidGasCalculator.GetRelativeHumidityFromDryBulbHumidityAndPressure(tg2, y2, p2);
                    if (fy > 1.0)
                    {
                        solveState = SolveState.NotSolved;
                        string msg = "Specified gas inlet state makes the relative humidity of the outlet greater than 1.0.";
                        throw new InappropriateSpecifiedValueException(msg);
                    }
                }
            }
            else if (tg2 != Constants.NO_VALUE && y2 != Constants.NO_VALUE)
            {
                ih = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(tg2, y2, p2);
                if (tg1 != Constants.NO_VALUE)
                {
                    y1 = humidGasCalculator.GetHumidityFromHumidEnthalpyTemperatureAndPressure(ih, tg1, p1);
                    Calculate(dgsInlet.MoistureContentDryBase, y1);
                    solveState = SolveState.Solved;
                }
                else if (y1 != Constants.NO_VALUE)
                {
                    tg1 = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(ih, y1, p1);
                    Calculate(dgsInlet.Temperature, tg1);
                    solveState = SolveState.Solved;
                }
                else if (td1 != Constants.NO_VALUE)
                {
                    y1  = humidGasCalculator.GetHumidityFromDewPointAndPressure(td1, p1);
                    tg1 = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(ih, y1, p1);
                    Calculate(dgsInlet.Temperature, tg1);
                    solveState = SolveState.Solved;
                }
                else if (fy1 != Constants.NO_VALUE)
                {
                    double fy_temp    = 0;
                    double delta      = 10.0;
                    double totalDelta = delta;
                    tg1 = tg2 + delta;
                    bool negativeLastTime = false;

                    int counter = 0;
                    do
                    {
                        counter++;
                        y1      = humidGasCalculator.GetHumidityFromHumidEnthalpyTemperatureAndPressure(ih, tg1, p1);
                        fy_temp = humidGasCalculator.GetRelativeHumidityFromDryBulbHumidityAndPressure(tg1, y1, p1);
                        if (fy1 < fy_temp)
                        {
                            if (negativeLastTime)
                            {
                                delta /= 2.0; //testing finds delta/2.0 is almost optimal
                            }
                            totalDelta      += delta;
                            negativeLastTime = false;
                        }
                        else if (fy1 > fy_temp)
                        {
                            delta           /= 2.0; //testing finds delta/2.0 is almost optimal
                            totalDelta      -= delta;
                            negativeLastTime = true;
                        }
                        tg1 = tg2 + totalDelta;
                    } while (Math.Abs(fy1 - fy_temp) > 1.0e-6 && counter <= 200);

                    if (counter < 200)
                    {
                        Calculate(dgsInlet.Temperature, tg1);
                        solveState = SolveState.Solved;
                    }
                }
            }
            //end of adiabatic saturation process calculatioin


            //have to recalculate the streams so that the following balance calcualtion
            //can have all the latest balance calculated values taken into account
            //PostSolve(false);
            UpdateStreamsIfNecessary();

            balanceModel.DoBalanceCalculation();

            double inletDustMassFlowRate      = Constants.NO_VALUE;
            double outletDustMassFlowRate     = Constants.NO_VALUE;
            double inletDustMoistureFraction  = 0.0;
            double outletDustMoistureFraction = 0.0;

            DryingGasComponents dgc;

            if (InletParticleLoading.HasValue && gasInlet.VolumeFlowRate.HasValue)
            {
                inletDustMassFlowRate = InletParticleLoading.Value * gasInlet.VolumeFlowRate.Value;
                dgc = dgsInlet.GasComponents;
                if (dgc.SolidPhase != null)
                {
                    SolidPhase        sp = dgc.SolidPhase;
                    MaterialComponent mc = sp[1];
                    inletDustMoistureFraction = mc.GetMassFractionValue();
                }
            }

            if (OutletParticleLoading.HasValue && gasOutlet.VolumeFlowRate.HasValue)
            {
                outletDustMassFlowRate = OutletParticleLoading.Value * gasOutlet.VolumeFlowRate.Value;
                dgc = dgsOutlet.GasComponents;
                if (dgc.SolidPhase != null)
                {
                    SolidPhase        sp = dgc.SolidPhase;
                    MaterialComponent mc = sp[1];
                    inletDustMoistureFraction = mc.GetMassFractionValue();
                }
            }

            double inletMoistureFlowRate  = Constants.NO_VALUE;
            double outletMoistureFlowRate = Constants.NO_VALUE;

            if (dgsInlet.MassFlowRateDryBase.HasValue && dgsInlet.MoistureContentDryBase.HasValue)
            {
                inletMoistureFlowRate = dgsInlet.MassFlowRateDryBase.Value * dgsInlet.MoistureContentDryBase.Value;
            }

            if (dgsOutlet.MassFlowRateDryBase.HasValue && dgsOutlet.MoistureContentDryBase.HasValue)
            {
                outletMoistureFlowRate = dgsOutlet.MassFlowRateDryBase.Value * dgsOutlet.MoistureContentDryBase.Value;
            }

            double materialFromGas = 0.0;

            if (inletDustMassFlowRate != Constants.NO_VALUE && outletDustMassFlowRate != Constants.NO_VALUE &&
                inletMoistureFlowRate != Constants.NO_VALUE && outletMoistureFlowRate != Constants.NO_VALUE)
            {
                double moistureToGas = outletMoistureFlowRate - inletMoistureFlowRate;
                materialFromGas = inletDustMassFlowRate - outletDustMassFlowRate;
                double moistureOfMaterialFromGas = inletDustMassFlowRate * inletDustMoistureFraction - outletDustMassFlowRate * outletDustMoistureFraction;

                if (dmsInlet.MassFlowRate.HasValue)
                {
                    double outletMassFlowRate = dmsInlet.MassFlowRate.Value + materialFromGas - moistureToGas;
                    Calculate(dmsOutlet.MassFlowRate, outletMassFlowRate);

                    if (dmsInlet.MoistureContentWetBase.HasValue)
                    {
                        double inletMaterialMoistureFlowRate  = dmsInlet.MassFlowRate.Value * dmsInlet.MoistureContentWetBase.Value;
                        double outletMaterialMoistureFlowRate = inletMaterialMoistureFlowRate - moistureToGas + moistureOfMaterialFromGas;
                        double outletMoistureContentWetBase   = outletMaterialMoistureFlowRate / outletMassFlowRate;
                        Calculate(dmsOutlet.MoistureContentWetBase, outletMoistureContentWetBase);
                        solveState = SolveState.Solved;
                    }
                    else if (dmsOutlet.MoistureContentWetBase.HasValue)
                    {
                        double outletMaterialMoistureFlowRate = dmsOutlet.MassFlowRate.Value * dmsInlet.MoistureContentWetBase.Value;
                        double inletMaterialMoistureFlowRate  = outletMaterialMoistureFlowRate + moistureToGas - moistureOfMaterialFromGas;
                        double inletMoistureContentWetBase    = inletMaterialMoistureFlowRate / dmsInlet.MassFlowRate.Value;
                        Calculate(dmsInlet.MoistureContentWetBase, inletMoistureContentWetBase);
                        solveState = SolveState.Solved;
                    }
                }
                else if (dmsOutlet.MassFlowRate.HasValue)
                {
                    double inletMassFlowRate = dmsOutlet.MassFlowRate.Value - materialFromGas + moistureToGas;
                    Calculate(dmsInlet.MassFlowRate, inletMassFlowRate);

                    if (dmsInlet.MoistureContentWetBase.HasValue)
                    {
                        double inletMaterialMoistureFlowRate  = dmsInlet.MassFlowRate.Value * dmsInlet.MoistureContentWetBase.Value;
                        double outletMaterialMoistureFlowRate = inletMaterialMoistureFlowRate - moistureToGas + moistureOfMaterialFromGas;
                        double outletMoistureContentWetBase   = outletMaterialMoistureFlowRate / dmsOutlet.MassFlowRate.Value;
                        Calculate(dmsOutlet.MoistureContentWetBase, outletMoistureContentWetBase);
                        solveState = SolveState.Solved;
                    }
                    else if (dmsOutlet.MoistureContentWetBase.HasValue)
                    {
                        double outletMaterialMoistureFlowRate = dmsOutlet.MassFlowRate.Value * dmsInlet.MoistureContentWetBase.Value;
                        double inletMaterialMoistureFlowRate  = outletMaterialMoistureFlowRate + moistureToGas - moistureOfMaterialFromGas;
                        double inletMoistureContentWetBase    = inletMaterialMoistureFlowRate / inletMassFlowRate;
                        Calculate(dmsInlet.MoistureContentWetBase, inletMoistureContentWetBase);
                        solveState = SolveState.Solved;
                    }
                }
                else if (dmsOutlet.MassConcentration.HasValue)
                {
                    double cValue            = dmsOutlet.MassConcentration.Value;
                    double inletMassFlowRate = (materialFromGas * (1 - cValue) + moistureToGas * cValue) / cValue;
                    Calculate(dmsInlet.MassFlowRate, inletMassFlowRate);
                    double outletMassFlowRate = inletMassFlowRate + materialFromGas - moistureToGas;
                    Calculate(dmsOutlet.MassFlowRate, outletMassFlowRate);
                    solveState = SolveState.Solved;
                }
            }

            MoistureProperties moistureProperties        = (this.unitOpSystem as EvaporationAndDryingSystem).GetMoistureProperties(((DryingMaterialStream)liquidInlet).MaterialComponents.Moisture.Substance);
            double             enthalpyOfMaterialFromGas = 0.0;

            if (dmsOutlet.GetCpOfAbsoluteDryMaterial() != Constants.NO_VALUE && inletDustMoistureFraction != Constants.NO_VALUE && gasInlet.Temperature.HasValue)
            {
                double tempValue = gasInlet.Temperature.Value;
                double liquidCp  = moistureProperties.GetSpecificHeatOfLiquid(tempValue);
                double specificHeatOfSolidPhase = (1.0 - inletDustMoistureFraction) * dmsOutlet.GetCpOfAbsoluteDryMaterial() + inletDustMoistureFraction * liquidCp;
                enthalpyOfMaterialFromGas = materialFromGas * specificHeatOfSolidPhase * (tempValue - 273.15);
            }

            if (gasInlet.SpecificEnthalpy.HasValue && gasInlet.MassFlowRate.HasValue &&
                gasOutlet.SpecificEnthalpy.HasValue && gasOutlet.MassFlowRate.HasValue)
            {
                double gasEnthalpyLoss = gasInlet.SpecificEnthalpy.Value * gasInlet.MassFlowRate.Value -
                                         gasOutlet.SpecificEnthalpy.Value * gasOutlet.MassFlowRate.Value;

                if (liquidInlet.SpecificEnthalpy.HasValue && liquidInlet.MassFlowRate.HasValue &&
                    liquidOutlet.MassFlowRate.HasValue)
                {
                    double totalLiquidOutletEnthalpy    = gasEnthalpyLoss + enthalpyOfMaterialFromGas + liquidInlet.SpecificEnthalpy.Value * liquidInlet.MassFlowRate.Value;
                    double specificLiquidOutletEnthalpy = totalLiquidOutletEnthalpy / liquidOutlet.MassFlowRate.Value;
                    Calculate(liquidOutlet.SpecificEnthalpy, specificLiquidOutletEnthalpy);
                }
                //else if (gasInlet.SpecificEnthalpy.HasValue && gasInlet.MassFlowRate.HasValue &&
                //               gasOutlet.SpecificEnthalpy.HasValue && gasOutlet.MassFlowRate.HasValue &&
                //               liquidOutlet.SpecificEnthalpy.HasValue && liquidOutlet.MassFlowRate.HasValue &&
                //               liquidInlet.MassFlowRate.HasValue) {
                //   double totalLiquidInletEnthalpy = liquidOutlet.SpecificEnthalpy.Value * liquidOutlet.MassFlowRate.Value - gasEnthalpyLoss - enthalpyOfMaterialFromGas;
                //   double specificLiquidInletEnthalpy = totalLiquidInletEnthalpy / liquidInlet.MassFlowRate.Value;
                //   Calculate(liquidInlet.SpecificEnthalpy, specificLiquidInletEnthalpy);
                //}
            }
            else if (liquidInlet.SpecificEnthalpy.HasValue && liquidInlet.MassFlowRate.HasValue &&
                     liquidOutlet.SpecificEnthalpy.HasValue && liquidOutlet.MassFlowRate.HasValue)
            {
                double liquidEnthalpyLoss = liquidInlet.SpecificEnthalpy.Value * liquidInlet.MassFlowRate.Value -
                                            liquidOutlet.SpecificEnthalpy.Value * liquidOutlet.MassFlowRate.Value;

                if (gasInlet.SpecificEnthalpy.HasValue && gasInlet.MassFlowRate.HasValue &&
                    gasOutlet.MassFlowRate.HasValue)
                {
                    double totalGasOutletEnthalpy    = liquidEnthalpyLoss + gasInlet.SpecificEnthalpy.Value * gasInlet.MassFlowRate.Value + enthalpyOfMaterialFromGas;
                    double specificGasOutletEnthalpy = totalGasOutletEnthalpy / gasOutlet.MassFlowRate.Value;
                    Calculate(gasOutlet.SpecificEnthalpy, specificGasOutletEnthalpy);
                }
                //else if (gasOutlet.SpecificEnthalpy.HasValue && gasOutlet.MassFlowRate.HasValue &&
                //               gasInlet.MassFlowRate.HasValue) {
                //   double totalGasInletEnthalpy = gasOutlet.SpecificEnthalpy.Value * gasOutlet.MassFlowRate.Value - liquidEnthalpyLoss;
                //   double specificGasInletEnthalpy = totalGasInletEnthalpy / gasInlet.MassFlowRate.Value;
                //   Calculate(gasInlet.SpecificEnthalpy, specificGasInletEnthalpy);
                //}
            }

            if (liquidToGasVolumeRatio.HasValue && gasInlet.VolumeFlowRate.HasValue)
            {
                //double recirculationVolumeFlow = liquidToGasVolumeRatio.Value * gasInlet.VolumeFlowRate.Value;
                //Calculate(liquidRecirculationVolumeFlowRate, recirculationVolumeFlow);
                //if (liquidOutlet.Density.HasValue) {
                //   double recirculationMassFlow = recirculationVolumeFlow / liquidOutlet.Density.Value;
                //   Calculate(liquidRecirculationMassFlowRate, recirculationMassFlow);
                //}
            }
        }
Beispiel #2
0
        public override void Execute(bool propagate)
        {
            //if dew point is known
            //HumidGasCalculator humidGasCalculator = GetHumidGasCalculator();
            if (dewPoint.HasValue)
            {
                if (relativeHumidity.HasValue && !temperature.IsSpecifiedAndHasValue)
                {
                    Calculate(temperature, HumidGasCalculator.GetDryBulbFromDewPointAndRelativeHumidity(dewPoint.Value, relativeHumidity.Value));
                }
                else if (pressure.HasValue)
                {
                    if (dewPoint.Value <= 1.0e-10 && !moistureContentDryBase.IsSpecifiedAndHasValue)
                    {
                        Calculate(moistureContentDryBase, 0);
                    }
                    else if (!moistureContentDryBase.IsSpecifiedAndHasValue)
                    {
                        Calculate(moistureContentDryBase, HumidGasCalculator.GetHumidityFromDewPointAndPressure(dewPoint.Value, pressure.Value));
                    }
                }
                //Pressure should always be known. So it should not be calculated
                else if (moistureContentDryBase.HasValue)
                {
                    //Calculate(pressure, humidGasCalculator.GetPressureFromDewPointAndHumidity(dewPoint.Value, humidity.Value));
                }
            }

            //if humidity is known
            if (moistureContentDryBase.HasValue)
            {
                if (pressure.HasValue && !dewPoint.IsSpecifiedAndHasValue)
                {
                    Calculate(dewPoint, HumidGasCalculator.GetDewPointFromHumidityAndPressure(moistureContentDryBase.Value, pressure.Value));
                }

                //to prevent repeated calculation of the same variable
                //if (relativeHumidity.HasValue && dewPoint.HasValue && !temperature.IsSpecifiedAndHasValue) {
                if (relativeHumidity.HasValue && dewPoint.HasValue && !temperature.HasValue)
                {
                    Calculate(temperature, HumidGasCalculator.GetDryBulbFromDewPointAndRelativeHumidity(dewPoint.Value, relativeHumidity.Value));
                }

                //to prevent repeated calculation of the same variable
                //if (wetBulbTemperature.HasValue && pressure.HasValue && !temperature.IsSpecifiedAndHasValue) {
                if (wetBulbTemperature.HasValue && pressure.HasValue && !temperature.HasValue)
                {
                    Calculate(temperature, HumidGasCalculator.GetDryBulbFromWetBulbHumidityAndPressure(wetBulbTemperature.Value, moistureContentDryBase.Value, pressure.Value));
                }
            }

            //to prevent repeated calculation of the same variable
            //if (wetBulbTemperature.HasValue && relativeHumidity.HasValue && pressure.HasValue
            //   && !temperature.IsSpecifiedAndHasValue) {
            if (wetBulbTemperature.HasValue && relativeHumidity.HasValue && pressure.HasValue &&
                !temperature.HasValue)
            {
                Calculate(temperature, HumidGasCalculator.GetDryBulbFromWetBulbRelativeHumidityAndPressure(wetBulbTemperature.Value, relativeHumidity.Value, pressure.Value));
            }

            double humidEnthalpyValue;
            double mcDryBase = moistureContentDryBase.Value;

            if (specificEnthalpy.HasValue && moistureContentDryBase.HasValue && !specificEnthalpyDryBase.HasValue)
            {
                Calculate(specificEnthalpyDryBase, specificEnthalpy.Value * (1.0 + mcDryBase));
            }

            //if (specificEnthalpyDryBase.HasValue && pressure.HasValue && !temperature.IsSpecifiedAndHasValue) {
            if (specificEnthalpyDryBase.HasValue && pressure.HasValue && !temperature.HasValue)
            {
                if (moistureContentDryBase.HasValue)
                {
                    Calculate(temperature, HumidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(specificEnthalpyDryBase.Value, moistureContentDryBase.Value, pressure.Value));
                }
                else if (relativeHumidity.HasValue)
                {
                    Calculate(temperature, HumidGasCalculator.GetDryBulbFromHumidEnthalpyRelativeHumidityAndPressure(specificEnthalpyDryBase.Value, relativeHumidity.Value, pressure.Value));
                }
                else if (dewPoint.HasValue)
                {
                    Calculate(temperature, HumidGasCalculator.GetDryBulbFromHumidEnthalpyDewPointAndPressure(specificEnthalpyDryBase.Value, relativeHumidity.Value, pressure.Value));
                }
                else if (wetBulbTemperature.HasValue)
                {
                    Calculate(temperature, HumidGasCalculator.GetDryBulbFromHumidEnthalpyWetBulbAndPressure(specificEnthalpyDryBase.Value, wetBulbTemperature.Value, pressure.Value));
                }
            }

            //if temperature is first known
            if (temperature.HasValue)
            {
                if (dewPoint.HasValue || relativeHumidity.HasValue)
                {
                    if (dewPoint.HasValue && !relativeHumidity.IsSpecifiedAndHasValue)
                    {
                        Calculate(relativeHumidity, HumidGasCalculator.GetRelativeHumidityFromDryBulbAndDewPoint(temperature.Value, dewPoint.Value));
                    }
                    else if (relativeHumidity.HasValue && !dewPoint.IsSpecifiedAndHasValue)
                    {
                        Calculate(dewPoint, HumidGasCalculator.GetDewPointFromDryBulbAndRelativeHumidity(temperature.Value, relativeHumidity.Value));
                    }

                    if (pressure.HasValue)
                    {
                        if (!moistureContentDryBase.IsSpecifiedAndHasValue)
                        {
                            Calculate(moistureContentDryBase, HumidGasCalculator.GetHumidityFromDewPointAndPressure(dewPoint.Value, pressure.Value));
                        }
                        if (!wetBulbTemperature.IsSpecifiedAndHasValue)
                        {
                            Calculate(wetBulbTemperature, HumidGasCalculator.GetWetBulbFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value));
                            //double satTemp = humidGasCalculator.GetSatTempFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value);
                        }
                    }
                    else if (moistureContentDryBase.HasValue)
                    {
                        if (!pressure.IsSpecifiedAndHasValue)
                        {
                            Calculate(pressure, HumidGasCalculator.GetPressureFromDewPointAndHumidity(dewPoint.Value, moistureContentDryBase.Value));
                        }
                        if (!wetBulbTemperature.IsSpecifiedAndHasValue)
                        {
                            Calculate(wetBulbTemperature, HumidGasCalculator.GetWetBulbFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value));
                            //double satTemp = humidGasCalculator.GetSatTempFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value);
                        }
                    }
                }
                else if (wetBulbTemperature.HasValue && pressure.HasValue)
                {
                    if (!moistureContentDryBase.IsSpecifiedAndHasValue)
                    {
                        Calculate(moistureContentDryBase, HumidGasCalculator.GetHumidityFromDryBulbWetBulbAndPressure(temperature.Value, wetBulbTemperature.Value, pressure.Value));
                    }
                    if (!relativeHumidity.IsSpecifiedAndHasValue)
                    {
                        Calculate(relativeHumidity, HumidGasCalculator.GetRelativeHumidityFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value));
                    }
                    if (!dewPoint.IsSpecifiedAndHasValue)
                    {
                        Calculate(dewPoint, HumidGasCalculator.GetDewPointFromDryBulbAndRelativeHumidity(temperature.Value, relativeHumidity.Value));
                    }
                }

                else if (moistureContentDryBase.HasValue && pressure.HasValue)
                {
                    if (!wetBulbTemperature.IsSpecifiedAndHasValue)
                    {
                        Calculate(wetBulbTemperature, HumidGasCalculator.GetWetBulbFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value));
                        //double satTemp = humidGasCalculator.GetSatTempFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value);
                    }

                    if (!relativeHumidity.IsSpecifiedAndHasValue)
                    {
                        Calculate(relativeHumidity, HumidGasCalculator.GetRelativeHumidityFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value));
                    }
                    if (!dewPoint.IsSpecifiedAndHasValue)
                    {
                        Calculate(dewPoint, HumidGasCalculator.GetDewPointFromDryBulbAndRelativeHumidity(temperature.Value, relativeHumidity.Value));
                    }
                }

                else if (wetBulbTemperature.HasValue && moistureContentDryBase.HasValue)
                {
                    //if (!pressure.IsSpecifiedAndHasValue) {
                    //   Calculate(pressure, humidGasCalculator.GetPressureFromDryBulbWetBulbAndHumidity(temperature.Value, wetBulbTemperature.Value, moistureContentDryBase.Value));
                    //}
                    if (!dewPoint.IsSpecifiedAndHasValue)
                    {
                        Calculate(dewPoint, HumidGasCalculator.GetDewPointFromHumidityAndPressure(temperature.Value, pressure.Value));
                    }
                    if (!relativeHumidity.IsSpecifiedAndHasValue)
                    {
                        Calculate(relativeHumidity, HumidGasCalculator.GetRelativeHumidityFromDryBulbAndDewPoint(temperature.Value, dewPoint.Value));
                    }
                }
            }

            mcDryBase = moistureContentDryBase.Value;
            if (moistureContentDryBase.HasValue && temperature.HasValue)
            {
                double cpDryBase = HumidGasCalculator.GetHumidHeat(moistureContentDryBase.Value, temperature.Value);
                Calculate(specificHeatDryBase, cpDryBase);
                Calculate(specificHeat, cpDryBase / (1.0 + mcDryBase));
                if (pressure.HasValue)
                {
                    double humidVolumeValue = HumidGasCalculator.GetHumidVolume(temperature.Value, moistureContentDryBase.Value, pressure.Value);
                    Calculate(humidVolume, humidVolumeValue);
                    humidEnthalpyValue = HumidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(temperature.Value, moistureContentDryBase.Value, pressure.Value);
                    Calculate(specificEnthalpyDryBase, humidEnthalpyValue);
                    Calculate(specificEnthalpy, humidEnthalpyValue / (1.0 + mcDryBase));
                    Calculate(density, (1.0 + mcDryBase) / humidVolumeValue);
                }
            }

            CalculateFlow();

            //if (temperature.HasValue && pressure.HasValue && massFlowRate.HasValue &&
            //   volumeFlowRate.HasValue && massFlowRateDryBase.HasValue && wetBulbTemperature.HasValue &&
            //   dewPoint.HasValue && moistureContentDryBase.HasValue && relativeHumidity.HasValue &&
            //   density.HasValue && specificEnthalpy.HasValue && specificHeatDryBase.HasValue) {
            //   solveState = SolveState.Solved;
            //}

            bool hasUnsolvedVar = false;

            foreach (ProcessVarDouble pv in varList)
            {
                if (!pv.HasValue)
                {
                    hasUnsolvedVar = true;
                    break;
                }
            }
            if (!hasUnsolvedVar)
            {
                solveState = SolveState.Solved;
            }
            //else
            //{
            //   foreach (ProcessVarDouble pv in varList)
            //   {
            //      if (!pv.IsSpecified && pv.HasValue)
            //      {
            //         solveState = SolveState.PartiallySolved;
            //         break;
            //      }
            //   }
            //}

            if (HasSolvedAlready)
            {
                DryingGasComponents dgc = (DryingGasComponents)materialComponents;
                //we cannot do a calculate operation since these variables are not in the
                //varList and they cannot be erased after they are initially calculated
                dgc.DryMedium.SetMassFractionValue(1.0 / (1.0 + Humidity.Value));
                dgc.Moisture.SetMassFractionValue(Humidity.Value / (1.0 + Humidity.Value));
                dgc.ComponentsFractionsChanged();
            }
            AdjustVarsStates();
            OnSolveComplete();
        }
Beispiel #3
0
        private void Solve()
        {
            double p   = pressure.Value;
            double tg1 = inputStream.Temperature.Value;
            double y1  = inputStream.Humidity.Value;
            double tw1 = inputStream.WetBulbTemperature.Value;
            double td1 = inputStream.DewPoint.Value;
            double fy1 = inputStream.RelativeHumidity.Value;

            double tg2 = outputStream.Temperature.Value;
            double y2  = outputStream.Humidity.Value;
            double tw2 = outputStream.WetBulbTemperature.Value;
            double td2 = outputStream.DewPoint.Value;
            double fy2 = outputStream.RelativeHumidity.Value;

            double ih = 0;

            if (inputStream.Pressure.Value != p)
            {
                Calculate(inputStream.Pressure, p);
            }
            if (outputStream.Pressure.Value != p)
            {
                Calculate(outputStream.Pressure, p);
            }

            HumidGasCalculator humidGasCalculator = GetHumidGasCalculator();

            if (tg1 != Constants.NO_VALUE && y1 != Constants.NO_VALUE)
            {
                //wetBulb = humidGasCalculator.GetWetBulbFromDryBulbHumidityAndPressure(tg1, y1, p);
                ih = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(tg1, y1, p);
                if (tg2 != Constants.NO_VALUE)
                {
                    y2 = humidGasCalculator.GetHumidityFromHumidEnthalpyTemperatureAndPressure(ih, tg2, p);
                    if (y2 <= 0.0)
                    {
                        y2 = 1.0e-6;
                    }

                    Calculate(outputStream.MoistureContentDryBase, y2);
                    solveState = SolveState.Solved;
                }
                else if (y2 != Constants.NO_VALUE)
                {
                    tg2 = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(ih, y2, p);
                    Calculate(outputStream.Temperature, tg2);
                    solveState = SolveState.Solved;
                }
                else if (td2 != Constants.NO_VALUE)
                {
                    y2  = humidGasCalculator.GetHumidityFromDewPointAndPressure(td2, p);
                    tg2 = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(ih, y2, p);
                    Calculate(outputStream.Temperature, tg2);
                    solveState = SolveState.Solved;
                }
                else if (fy2 != Constants.NO_VALUE)
                {
                    double fy_temp    = 0;
                    double delta      = 10.0;
                    double totalDelta = delta;
                    tg2 = tg1 - delta;
                    bool negativeLastTime = false;

                    int counter = 0;
                    do
                    {
                        counter++;
                        y2      = humidGasCalculator.GetHumidityFromHumidEnthalpyTemperatureAndPressure(ih, tg2, p);
                        fy_temp = humidGasCalculator.GetRelativeHumidityFromDryBulbHumidityAndPressure(tg2, y2, p);
                        if (fy2 > fy_temp)
                        {
                            if (negativeLastTime)
                            {
                                delta /= 2.0; //testing finds delta/2.0 is almost optimal
                            }
                            totalDelta      += delta;
                            negativeLastTime = false;
                        }
                        else if (fy2 < fy_temp)
                        {
                            delta           /= 2.0; //testing finds delta/2.0 is almost optimal
                            totalDelta      -= delta;
                            negativeLastTime = true;
                        }
                        tg2 = tg1 - totalDelta;
                    } while (Math.Abs(fy2 - fy_temp) > 1.0e-6 && counter <= 200);

                    if (counter < 200)
                    {
                        Calculate(outputStream.Temperature, tg2);
                        solveState = SolveState.Solved;
                    }
                }

                double fy = humidGasCalculator.GetRelativeHumidityFromDryBulbHumidityAndPressure(tg2, y2, p);
                if (fy > 1.0)
                {
                    solveState = SolveState.NotSolved;
                    string msg = "Specified input state makes the relative humidity of the output greater than 1.0.";
                    throw new InappropriateSpecifiedValueException(msg);
                }
            }
            else if (tg2 != Constants.NO_VALUE && y2 != Constants.NO_VALUE)
            {
                ih = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(tg2, y2, p);
                if (tg1 != Constants.NO_VALUE)
                {
                    y1 = humidGasCalculator.GetHumidityFromHumidEnthalpyTemperatureAndPressure(ih, tg1, p);
                    Calculate(inputStream.MoistureContentDryBase, y1);
                    solveState = SolveState.Solved;
                }
                else if (y1 != Constants.NO_VALUE)
                {
                    tg1 = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(ih, y1, p);
                    Calculate(inputStream.Temperature, tg1);
                    solveState = SolveState.Solved;
                }
                else if (td1 != Constants.NO_VALUE)
                {
                    y1  = humidGasCalculator.GetHumidityFromDewPointAndPressure(td1, p);
                    tg1 = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(ih, y1, p);
                    Calculate(inputStream.Temperature, tg1);
                    solveState = SolveState.Solved;
                }
                else if (fy1 != Constants.NO_VALUE)
                {
                    double fy_temp    = 0;
                    double delta      = 10.0;
                    double totalDelta = delta;
                    tg1 = tg2 + delta;
                    bool negativeLastTime = false;

                    int counter = 0;
                    do
                    {
                        counter++;
                        y1      = humidGasCalculator.GetHumidityFromHumidEnthalpyTemperatureAndPressure(ih, tg1, p);
                        fy_temp = humidGasCalculator.GetRelativeHumidityFromDryBulbHumidityAndPressure(tg1, y1, p);
                        if (fy1 < fy_temp)
                        {
                            if (negativeLastTime)
                            {
                                delta /= 2.0; //testing finds delta/2.0 is almost optimal
                            }
                            totalDelta      += delta;
                            negativeLastTime = false;
                        }
                        else if (fy1 > fy_temp)
                        {
                            delta           /= 2.0; //testing finds delta/2.0 is almost optimal
                            totalDelta      -= delta;
                            negativeLastTime = true;
                        }
                        tg1 = tg2 + totalDelta;
                    } while (Math.Abs(fy1 - fy_temp) > 1.0e-6 && counter <= 200);

                    if (counter < 200)
                    {
                        Calculate(inputStream.Temperature, tg1);
                        solveState = SolveState.Solved;
                    }
                }
            }
        }
Beispiel #4
0
        private void Solve()
        {
            double totalEenthalpyOfReactantInFuelInlet = 0;
            double moleFractionCarbon   = 0;
            double moleFractionHydrogen = 0;
            double moleFractionSulfur   = 0;
            double moleFractionOxygen   = 0;
            //double massAsh = 0;
            double             moleFractionCarbonDioxide = 0;
            double             moleFractionNitrogen      = 0; //mole fraction of nitrogen in original gas fuel
            MaterialComponents components = fuelInlet.Components;

            if (fuelInlet is GenericFuelStream)
            {
                for (int i = 0; i < components.Count; i++)
                {
                    MaterialComponent component   = components[i];
                    Substance         mySubstance = component.Substance;
                    //myMassFraction = component.MassFraction.Value;
                    double myMoleFraction = component.MoleFraction.Value;
                    if (mySubstance == carbon)
                    {
                        moleFractionCarbon = myMoleFraction;
                    }
                    else if (mySubstance == hydrogen)
                    {
                        moleFractionHydrogen = myMoleFraction;
                    }
                    else if (mySubstance == oxygen)
                    {
                        moleFractionOxygen = myMoleFraction;
                    }
                    else if (mySubstance == sulfur)
                    {
                        moleFractionSulfur = myMoleFraction;
                    }
                    //else if (component.Substance == ash) {
                    //   massAsh = myMassFraction;
                    //}
                }
            }
            else if (fuelInlet is DetailedFuelStream)
            {
                totalEenthalpyOfReactantInFuelInlet = 0;
                moleFractionCarbon   = 0;
                moleFractionHydrogen = 0;
                moleFractionOxygen   = 0;
                moleFractionSulfur   = 0;
                double t = fuelInlet.Temperature.Value;
                for (int i = 0; i < components.Count; i++)
                {
                    MaterialComponent component      = components[i];
                    Substance         mySubstance    = component.Substance;
                    double            myMoleFraction = component.MoleFraction.Value;

                    if (mySubstance == carbonDioxide)
                    {
                        moleFractionCarbonDioxide = myMoleFraction;
                    }
                    else if (mySubstance == nitrogen)
                    {
                        moleFractionNitrogen = myMoleFraction;
                    }
                    else
                    {
                        totalEenthalpyOfReactantInFuelInlet += myMoleFraction * propCalculator.CalculateEnthalpyOfFormation(t, mySubstance);
                        SubstanceFormula formula  = mySubstance.Formula;
                        string[]         elements = formula.Elements;
                        foreach (string element in elements)
                        {
                            int elementCount = formula.GetElementCount(element);
                            if (element == "C")
                            {
                                moleFractionCarbon += elementCount * myMoleFraction;
                            }
                            else if (element == "H")
                            {
                                moleFractionHydrogen += elementCount * myMoleFraction;
                            }
                            else if (element == "O")
                            {
                                moleFractionOxygen += elementCount * myMoleFraction;
                            }
                            else if (element == "S")
                            {
                                moleFractionSulfur += elementCount * myMoleFraction;
                            }
                        }
                    }
                }
            }

            moleFractionHydrogen = 0.5 * moleFractionHydrogen; //convert from H to H2
            moleFractionOxygen   = 0.5 * moleFractionOxygen;   //convert from O to O2

            //multiply 0.5 for moleFractionHydrogen because 1 mole of H2 only needs 0.5 mole of O2
            double moleFractionOxygenNeeded = moleFractionCarbon + 0.5 * moleFractionHydrogen + moleFractionSulfur - moleFractionOxygen;
            double exactDryAirMassNeeded    = moleFractionOxygenNeeded / OXYGEN_MOLE_FRACTION_IN_AIR * air.MolarWeight;

            double excessAirValue                = excessAir.HasValue ? excessAir.Value / 100 : 0;
            double excessDryAirNeeded            = exactDryAirMassNeeded * excessAirValue;
            double dryAirMassNeeded              = exactDryAirMassNeeded + excessDryAirNeeded;
            double moistureMassCarriedByInletAir = dryAirMassNeeded * airInlet.Humidity.Value;
            double airMassNeeded = dryAirMassNeeded + moistureMassCarriedByInletAir;

            double moitureGeneratedByReaction = moleFractionHydrogen * water.MolarWeight; //since 1 mole of H2 generates 1 mole of water
            double totalMoistureInFlueGas     = moitureGeneratedByReaction + moistureMassCarriedByInletAir;

            double flueGasTotal = airMassNeeded + fuelInlet.Components.MolarWeight;
            double dryFlueGas   = flueGasTotal - totalMoistureInFlueGas;
            double flueGasMoistureContentDryBase = totalMoistureInFlueGas / dryFlueGas;

            CompositeSubstance  flueGas           = CreateDryFlueGasSubstance(moleFractionCarbon, moleFractionSulfur, moleFractionCarbonDioxide, moleFractionNitrogen, moleFractionOxygenNeeded, dryAirMassNeeded, dryFlueGas, excessAirValue);
            DryingGasComponents flueGasComponents = CreateDryingGasComponents(flueGasMoistureContentDryBase, flueGas);

            flueGasOutlet.GasComponents = flueGasComponents;

            double fuelMoleFlowRate = fuelInlet.MoleFlowRate.Value;

            if (excessAir.HasValue)
            {
                Calculate(flueGasOutlet.Humidity, flueGasMoistureContentDryBase);

                if (fuelInlet.MoleFlowRate.HasValue)
                {
                    Calculate(airInlet.MassFlowRateDryBase, dryAirMassNeeded * fuelMoleFlowRate);
                    Calculate(flueGasOutlet.MassFlowRate, flueGasTotal * fuelMoleFlowRate);
                }
                else if (flueGasOutlet.MassFlowRate.HasValue)
                {
                    fuelMoleFlowRate = flueGasOutlet.MassFlowRate.Value / flueGasTotal;
                    Calculate(fuelInlet.MoleFlowRate, fuelMoleFlowRate);
                    Calculate(airInlet.MassFlowRateDryBase, dryAirMassNeeded * fuelMoleFlowRate);
                }
            }

            double fuelInletEnthalpy  = fuelInlet.SpecificEnthalpy.Value;
            double airInletEnthalpy   = airMassNeeded * airInlet.SpecificEnthalpy.Value;
            double totalHeatGenerated = Constants.NO_VALUE;
            double heatLossValue      = 0;

            if (fuelInlet is GenericFuelStream)
            {
                //GenericFuelStream gfs = fuelInlet as GenericFuelStream;
                //if (gfs.HeatValue.HasValue) {
                //   //total heat genrate eaquls to heat value of the fuel times fuelMassFlowRate
                //   totalHeatGenerated = gfs.HeatValue.Value * fuelMoleFlowRate;

                //   heatLossValue = totalHeatGenerated * percentageHeatLoss.Value / 100;

                //   double totalFlueGasSpecificEnthalpy = (fuelInletEnthalpy + airInletEnthalpy + totalHeatGenerated - heatLossValue) / flueGasTotal;
                //   Calculate(flueGasOutlet.SpecificEnthalpy, totalFlueGasSpecificEnthalpy);
                //}
            }
            else if (fuelInlet is DetailedFuelStream)
            {
                HumidGasCalculator humidGasCalculator = new HumidGasCalculator(flueGas, water);

                //evaporation heat of 2 moles of water
                double evaporationHeat = 2.0 * water.MolarWeight * humidGasCalculator.GetEvaporationHeat(273.15);
                double p = flueGasOutlet.Pressure.Value;
                //double originalTemperature = airInlet.Temperature.Value;
                //double initialHumidEnthalpy = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(originalTemperature, flueGasMoistureContentDryBase, p);
                double initialHumidEnthalpy = airInlet.SpecificEnthalpyDryBase.Value;
                initialHumidEnthalpy = initialHumidEnthalpy * dryAirMassNeeded / dryFlueGas;
                double t = airInlet.Temperature.Value;
                double totalEnthalpyOfReactantOxygen = moleFractionOxygenNeeded * propCalculator.CalculateEnthalpyOfFormation(t, oxygen);
                double totalEenthalpyOfReactants     = totalEenthalpyOfReactantInFuelInlet + totalEnthalpyOfReactantOxygen;

                double tNew    = t;
                int    counter = 0;
                if (excessAir.HasValue && percentageHeatLoss.IsSpecifiedAndHasValue)
                {
                    do
                    {
                        counter++;
                        t = tNew;
                        double totalEenthalpyOfProduct = CalculateTotalEntalpyOfProduct(moleFractionCarbon, moleFractionHydrogen, moleFractionSulfur, t);
                        totalHeatGenerated = totalEenthalpyOfReactants - totalEenthalpyOfProduct + evaporationHeat;

                        heatLossValue = totalHeatGenerated * percentageHeatLoss.Value / 100;

                        double flueGasHumidEnthalpy = initialHumidEnthalpy + (totalHeatGenerated - heatLossValue) / dryFlueGas;
                        tNew = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(flueGasHumidEnthalpy, flueGasMoistureContentDryBase, p);
                    } while (Math.Abs(tNew - t) / tNew > 1.0e-8 && counter < 100);

                    if (counter == 100)
                    {
                        throw new CalculationFailedException("Calculation of flame temperature failed.");
                    }

                    Calculate(flueGasOutlet.Temperature, tNew);
                    totalHeatGenerated *= fuelMoleFlowRate;

                    Calculate(heatLoss, totalHeatGenerated * percentageHeatLoss.Value / 100);
                }
                else if (excessAir.HasValue && flueGasOutlet.Temperature.IsSpecifiedAndHasValue)
                {
                    double flueGasTemp             = flueGasOutlet.Temperature.Value;
                    double totalEenthalpyOfProduct = CalculateTotalEntalpyOfProduct(moleFractionCarbon, moleFractionHydrogen, moleFractionSulfur, flueGasTemp);
                    totalHeatGenerated = totalEenthalpyOfReactants - totalEenthalpyOfProduct + evaporationHeat;
                    heatLossValue      = totalHeatGenerated * percentageHeatLoss.Value / 100;
                    double flueGasHumidEnthalpy = initialHumidEnthalpy + (totalHeatGenerated - heatLossValue) / dryFlueGas;
                    tNew = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(flueGasHumidEnthalpy, flueGasMoistureContentDryBase, p);

                    if (tNew < flueGasTemp)
                    {
                        throw new CalculationFailedException("Specified flue gas temperature cannot be reached.");
                    }

                    counter = 0;
                    double humidEnthanlpy0 = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(flueGasTemp, flueGasMoistureContentDryBase, p);
                    do
                    {
                        counter++;
                        double humidEnthanlpy1 = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(tNew, flueGasMoistureContentDryBase, p);
                        heatLossValue       += dryFlueGas * (humidEnthanlpy1 - humidEnthanlpy0);
                        flueGasHumidEnthalpy = initialHumidEnthalpy + (totalHeatGenerated - heatLossValue) / dryFlueGas;
                        tNew = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(flueGasHumidEnthalpy, flueGasMoistureContentDryBase, p);
                    } while (Math.Abs(tNew - flueGasTemp) / flueGasTemp > 1.0e-8 && counter < 100);

                    if (counter == 100)
                    {
                        throw new CalculationFailedException("Calculation of flame temperature failed.");
                    }

                    totalHeatGenerated *= fuelMoleFlowRate;
                    heatLossValue      *= fuelMoleFlowRate;

                    Calculate(heatLoss, heatLossValue);
                    Calculate(percentageHeatLoss, heatLossValue / totalHeatGenerated * 100);
                }
                else if (flueGasOutlet.Temperature.IsSpecifiedAndHasValue && percentageHeatLoss.IsSpecifiedAndHasValue)
                {
                    double flueGasTemp             = flueGasOutlet.Temperature.Value;
                    double totalEenthalpyOfProduct = CalculateTotalEntalpyOfProduct(moleFractionCarbon, moleFractionHydrogen, moleFractionSulfur, flueGasTemp);
                    totalHeatGenerated = totalEenthalpyOfReactants - totalEenthalpyOfProduct + evaporationHeat;

                    heatLossValue = totalHeatGenerated * percentageHeatLoss.Value / 100;
                    double flueGasHumidEnthalpy = initialHumidEnthalpy + (totalHeatGenerated - heatLossValue) / dryFlueGas;
                    tNew = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(flueGasHumidEnthalpy, flueGasMoistureContentDryBase, p);

                    if (tNew < flueGasTemp)
                    {
                        throw new CalculationFailedException("Specified flue gas temperature cannot be reached.");
                    }

                    //double excessDryAirNeededOld;
                    do
                    {
                        counter++;
                        t = tNew;
                        //excessDryAirNeededOld = excessDryAirNeeded;
                        //initialHumidEnthalpy = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(originalTemperature, flueGasMoistureContentDryBase, p);
                        flueGasHumidEnthalpy = humidGasCalculator.GetHumidEnthalpyFromDryBulbHumidityAndPressure(flueGasTemp, flueGasMoistureContentDryBase, p);
                        dryFlueGas           = (totalHeatGenerated - heatLossValue) / (flueGasHumidEnthalpy - initialHumidEnthalpy);

                        flueGasTotal  = dryFlueGas + totalMoistureInFlueGas;
                        airMassNeeded = flueGasTotal - fuelInlet.Components.MolarWeight;

                        dryAirMassNeeded       = airMassNeeded / (1 + airInlet.Humidity.Value);
                        totalMoistureInFlueGas = moitureGeneratedByReaction + dryAirMassNeeded * airInlet.Humidity.Value;
                        excessDryAirNeeded     = dryAirMassNeeded - exactDryAirMassNeeded;
                        excessAirValue         = excessDryAirNeeded / exactDryAirMassNeeded;

                        flueGasMoistureContentDryBase = totalMoistureInFlueGas / dryFlueGas;

                        flueGas            = CreateDryFlueGasSubstance(moleFractionCarbon, moleFractionSulfur, moleFractionCarbonDioxide, moleFractionNitrogen, moleFractionOxygenNeeded, dryAirMassNeeded, dryFlueGas, excessAirValue);
                        humidGasCalculator = new HumidGasCalculator(flueGas, water);

                        tNew = humidGasCalculator.GetDryBulbFromHumidEnthalpyHumidityAndPressure(flueGasHumidEnthalpy, flueGasMoistureContentDryBase, p);
                    } while (Math.Abs(tNew - flueGasTemp) / flueGasTemp > 1.0e-8 && counter < 100);
                    //} while (Math.Abs(excessDryAirNeeded - excessDryAirNeededOld) > 1.0e-6 && counter < 100);

                    if (counter == 100)
                    {
                        throw new CalculationFailedException("Calculation of flame temperature failed.");
                    }

                    Calculate(flueGasOutlet.Humidity, flueGasMoistureContentDryBase);
                    Calculate(excessAir, excessAirValue * 100);
                    flueGasComponents           = CreateDryingGasComponents(flueGasMoistureContentDryBase, flueGas);
                    flueGasOutlet.GasComponents = flueGasComponents;

                    if (flueGasOutlet.MassFlowRate.IsSpecifiedAndHasValue)
                    {
                        fuelMoleFlowRate = flueGasOutlet.MassFlowRate.Value / flueGasTotal;
                        Calculate(fuelInlet.MoleFlowRate, fuelMoleFlowRate);
                    }
                    else
                    {
                        Calculate(flueGasOutlet.MassFlowRate, flueGasTotal * fuelMoleFlowRate);
                    }

                    Calculate(airInlet.MassFlowRateDryBase, dryAirMassNeeded * fuelMoleFlowRate);
                    Calculate(heatLoss, heatLossValue * fuelMoleFlowRate);

                    totalHeatGenerated *= fuelMoleFlowRate;
                }

                Calculate(totalHeatGeneration, totalHeatGenerated);
            }

            if (flueGasOutlet.Temperature.HasValue && totalHeatGeneration.HasValue)
            {
                solveState = SolveState.Solved;
                double oxygenMassFraction = moleFractionOxygenNeeded * excessAirValue * oxygen.MolarWeight / flueGasTotal;
                double oxygenMoleFraction = moleFractionOxygenNeeded * excessAirValue / (1 + airMassNeeded / air.MolarWeight);
                Calculate(oxygenMassFractionFlueGas, oxygenMassFraction);
                Calculate(oxygenMoleFractionFlueGas, oxygenMoleFraction);
            }
        }