Beispiel #1
0
        public double output(IF97Parameters key, double T, double p)
        {
            switch (key)
            {
            case IF97Parameters.T: return(T);

            case IF97Parameters.p: return(p);

            case IF97Parameters.d: return(rhomass(T, p));

            case IF97Parameters.h: return(hmass(T, p));

            case IF97Parameters.s: return(smass(T, p));

            case IF97Parameters.u: return(umass(T, p));

            case IF97Parameters.cp: return(cpmass(T, p));

            case IF97Parameters.cv: return(cvmass(T, p));

            case IF97Parameters.w: return(speed_sound(T, p));

            case IF97Parameters.mu: return(visc(T, rhomass(T, p)));     // Viscosity is a function of rho.

            case IF97Parameters.tc: return(tcond(T, p, rhomass(T, p))); // Conductivity needs p and rho.

            case IF97Parameters.drhodp: return(drhodp(T, p));           // For verification testing.
            }
            throw new ArgumentOutOfRangeException("Unable to match input parameters");
        }
Beispiel #2
0
        static double RegionOutputBackward(double p, double X, IF97Parameters inkey)
        {
            // Note that this routine returns only temperature (IF97_T).  All other values should be
            // calculated from this temperature and the known pressure using forward equations.
            // Setup Backward Regions for output

            // Make sure input and output keys are valid for Backward formulas
            if ((inkey != IF97Parameters.h) && (inkey != IF97Parameters.s))
                throw new ArgumentException("Backward Formulas take variable inputs of Enthalpy or Entropy only.");

            // Get Saturation Parameters

            IF97REGIONS region = RegionDetermination_pX(p, X, inkey);

            switch (region)
            {
                case IF97REGIONS.REGION_1:
                    if (inkey == IF97Parameters.h)
                        return B1H.T_pX(p, X);
                    else
                        return B1S.T_pX(p, X);
                case IF97REGIONS.REGION_2:
                    if (inkey == IF97Parameters.h)
                    {
                        if (p <= 4.0)
                            return B2aH.T_pX(p, X);
                        else if (X >= BackwardsRegion.H2b2c_p(p))
                            return B2bH.T_pX(p, X);
                        else
                            return B2cH.T_pX(p, X);
                    }
                    else
                    {
                        if (p <= 4.0)
                            return B2aS.T_pX(p, X);
                        else if (X >= Constants.S2bc)
                            return B2bS.T_pX(p, X);
                        else
                            return B2cS.T_pX(p, X);
                    };
                case IF97REGIONS.REGION_3:
                    if (inkey == IF97Parameters.h)
                    {
                        if (X <= BackwardsRegion.H3ab_p(p))
                            return B3aH.T_pX(p, X);
                        else
                            return B3bH.T_pX(p, X);
                    }
                    else
                    {
                        if (X <= Constants.Scrit)
                            return B3aS.T_pX(p, X);
                        else
                            return B3bS.T_pX(p, X);
                    };
                case IF97REGIONS.REGION_4: return Tsat97(p);
                default: throw new ArgumentOutOfRangeException("Unable to match region");
            }
        }  // Region Output backward
Beispiel #3
0
        static IF97REGIONS RegionDetermination_pX(double p, double X, IF97Parameters inkey)
        {
            // Setup needed Region Equations for region determination

            // Saturation Region Limit Variables
            double Tsat = 0;
            double Xliq = 0;
            double Xvap = 0;

            // Check overall boundary limits
            if ((p < Constants.Pmin) || (p > Constants.Pmax))
                throw new ArgumentOutOfRangeException("Pressure out of range");
            double Xmin = R1.output(inkey, Constants.Tmin, p);
            double Xmax = R2.output(inkey, Constants.Tmax, p);
            if ((X < Xmin) || (X > (Xmax + 1.0E-10)))
            {
                if (inkey == IF97Parameters.h)
                {
                    throw new ArgumentOutOfRangeException("Enthalpy out of range");
                }
                else
                {
                    throw new ArgumentOutOfRangeException("Entropy out of range");
                }
            }

            // Check saturation Dome first
            if (p <= Constants.Pcrit)
            {
                Tsat = Region4.Tsat97(p);
                Xliq = R1.output(inkey, Tsat, p);
                Xvap = R2.output(inkey, Tsat, p);
                if ((Xliq <= X) && (X <= Xvap))
                {    // Within Saturation Dome
                    return IF97REGIONS.REGION_4;               //    Region 4
                }
            }
            // End Check saturation Dome

            // Check values below 16.529 MPa
            if (p <= Constants.P23min)
            {                        // p <= P23min (saturation dome)
                if (X <= Xliq) return IF97REGIONS.REGION_1;
                else if (X >= Xvap) return IF97REGIONS.REGION_2;
                else return IF97REGIONS.REGION_4;
            }
            // Check values above 16.529 MPa
            else if (X <= R1.output(inkey, Constants.T23min, p))
                return IF97REGIONS.REGION_1;
            else if (X >= R2.output(inkey, Region23_p(p), p))
                return IF97REGIONS.REGION_2;
            else
                return IF97REGIONS.REGION_3;
        } // Region Output backward
Beispiel #4
0
 static double Q_pX(double p, double X, IF97Parameters inkey)
 {
     double Xliq, Xvap;
     if ((p < Constants.Pmin) || (p > Constants.Pmax))
     {
         throw new ArgumentOutOfRangeException("Pressure out of range");
     }
     else if (p < Constants.Ptrip)
     {
         return 0;  //Liquid, at all temperatures
     }
     else if (p > Constants.Pcrit)
     {
         double t;
         switch (inkey)
         {
             case IF97Parameters.h:
             case IF97Parameters.s:
                 t = RegionOutputBackward(p, X, inkey); break;
             case IF97Parameters.u:
             case IF97Parameters.d:
             default:
                 // There are no reverse functions for t(p,U) or t(p,rho)
                 throw new ArgumentException("Quality cannot be determined for these inputs.");
         }
         if (t < Constants.Tcrit)
             return 1.0;  // Vapor, at all pressures above critical point
         else
             // Supercritical Region (p>Pcrit) && (t>Tcrit)
             throw new ArgumentException("Quality not defined in supercritical region.");
     }
     else
     {
         switch (inkey)
         {
             case IF97Parameters.h:
             case IF97Parameters.s:
             case IF97Parameters.u:
                 Xliq = RegionOutput(inkey, Tsat97(p), p, SatState.LIQUID);
                 Xvap = RegionOutput(inkey, Tsat97(p), p, SatState.VAPOR);
                 return Math.Min(1.0, Math.Max(0.0, (X - Xliq) / (Xvap - Xliq)));
             case IF97Parameters.d:
                 Xliq = 1.0 / RegionOutput(IF97Parameters.d, Tsat97(p), p, SatState.LIQUID);
                 Xvap = 1.0 / RegionOutput(IF97Parameters.d, Tsat97(p), p, SatState.VAPOR);
                 X = 1.0 / X;
                 return Math.Min(1.0, Math.Max(0.0, (X - Xliq) / (Xvap - Xliq)));
             default:
                 throw new ArgumentException("Quality cannot be determined for these inputs.");
         }
     }
     // If all else fails, which it shouldn't...
     throw new ArgumentException("Quality cannot be determined for these inputs.");
 }
Beispiel #5
0
        static double BackwardOutputHS(IF97Parameters outkey, double h, double s)
        {
            // Note that this routine returns only temperature (IF97_T).  All other values should be
            // calculated from this temperature and the known pressure using forward equations.
            // Setup Backward Regions for output
            //
            double Pval = 0, Tval = 0;

            // Make sure output keys are valid for Backward_HS formulas
            if ((outkey != IF97Parameters.p) && (outkey != IF97Parameters.T))
                throw new ArgumentException("Backward HS Formulas output Temperature or Pressure only.");

            // Get Saturation Parameters

            IF97BACKREGIONS region = RegionDetermination_HS(h, s);

            switch (region)
            {
                case IF97BACKREGIONS.BACK_1: Pval = B1HS.p_hs(h, s); break;
                case IF97BACKREGIONS.BACK_2A: Pval = B2aHS.p_hs(h, s); break;
                case IF97BACKREGIONS.BACK_2B: Pval = B2bHS.p_hs(h, s); break;
                case IF97BACKREGIONS.BACK_2C: Pval = B2cHS.p_hs(h, s); break;
                case IF97BACKREGIONS.BACK_3A: Pval = B3aHS.p_hs(h, s); break;
                case IF97BACKREGIONS.BACK_3B: Pval = B3bHS.p_hs(h, s); break;
                case IF97BACKREGIONS.BACK_4:
                    if (s >= Constants.SgT23)   // T(h,s) only defined over part of the 2-phase region
                        Tval = B4HS.t_hs(h, s);
                    else
                        throw new ArgumentOutOfRangeException("Entropy out of range");
                    break;
                default: throw new ArgumentOutOfRangeException("Unable to match region");
            }
            if (outkey == IF97Parameters.p)            // Returning Pressure (IF97_P)
                if (region == IF97BACKREGIONS.BACK_4)        //
                    return psat97(Tval);     //       Not REGION 4, already have pressure
                else                         // 
                    return Pval;             //       REGION 4, Calculate Psat from Tsat
                                             //
            else                             // ELSE Returning Temperature
                if (region == IF97BACKREGIONS.BACK_4)        //
                return Tval;                                     // REGION 4, already have Temperature
            else                                                 //
                return RegionOutputBackward(Pval, h, IF97Parameters.h);  // Not REGION 4 Calc from Backward T(p,h)
        }  // Region Output backward
Beispiel #6
0
        }  // SatSubRegionAdjust

        public static double output(IF97Parameters key, double T, double p, SatState State)
        {
            double rho;
            char   region = BackwardsRegion3.RegionDetermination(T, p);

            // if this is a saturated vapor or liquid function, make sure we're on
            // the correct side of the saturation curve and adjust region before
            // calculating density.
            region = SatSubRegionAdjust(State, p, region);

            rho = 1 / BackwardsRegion3.Region3_v_TP(region, T, p);

#if REGION3_ITERATE
            // Use previous rho value from algebraic equations
            //      as an initial guess to solve rhomass iteratively
            //      with Newton-Raphson
            rho = rhomass(T, p, rho);
#endif
            switch (key)                 // return all properties using the new rho value
            {
            case IF97Parameters.d: return(rho);

            case IF97Parameters.h: return(hmass(T, rho));

            case IF97Parameters.s: return(smass(T, rho));

            case IF97Parameters.u: return(umass(T, rho));

            case IF97Parameters.cp: return(cpmass(T, rho));

            case IF97Parameters.cv: return(cvmass(T, rho));

            case IF97Parameters.w: return(speed_sound(T, rho));

            case IF97Parameters.mu: return(visc(T, rho));

            case IF97Parameters.tc: return(tcond(T, p, rho));

            case IF97Parameters.drhodp: return(drhodp(T, rho));

            default:
                throw new ArgumentException("Bad key to output");      // JPH: changed this to invalid_argument exception
            }
        }
Beispiel #7
0
        } // Region Output backward

        static int BackwardRegion(double p, double X, IF97Parameters inkey)
        {
            // This routine is for testing purposes only.  It returns the
            // Region as an integer based on the backward evaluation of either
            // (p,h) or (p,s)

            // Make sure input and output keys are valid for Backward formulas
            if ((inkey != IF97Parameters.h) && (inkey != IF97Parameters.s))
                throw new ArgumentException("Backward Formulas take variable inputs of Enthalpy or Entropy only.");

            IF97REGIONS region = RegionDetermination_pX(p, X, inkey);

            switch (region)
            {
                case IF97REGIONS.REGION_1: return 1;
                case IF97REGIONS.REGION_2: return 2;
                case IF97REGIONS.REGION_3: return 3;
                case IF97REGIONS.REGION_4: return 4;
                default: return 0;
            }
        }
Beispiel #8
0
        }  // Region Output backward

        static double rho_pX(double p, double X, IF97Parameters inkey)
        {
            // NOTE: This implementation works, and with the 2016 Supplementary Release
            //       for v(p,T) for Region 3 implemented, it is no longer iterative.  
            //       However, the 2014 Supplementary Release for v(p,h) and v(p,s) are 
            //       more direct and may be slightly faster, since only one algebraic 
            //       equation is needed instead of two in Region 3.
            double T = RegionOutputBackward(p, X, inkey);
            if (RegionDetermination_pX(p, X, inkey) == IF97REGIONS.REGION_4)
            {      // If in saturation dome
                double Tsat = Tsat97(p);
                double Xliq = R1.output(inkey, Tsat, p);
                double Xvap = R2.output(inkey, Tsat, p);
                double vliq = 1.0 / R1.output(IF97Parameters.d, Tsat, p);
                double vvap = 1.0 / R2.output(IF97Parameters.d, Tsat, p);
                return 1.0 / (vliq + (X - Xliq) * (vvap - vliq) / (Xvap - Xliq));  //    Return Mixture Density
            }
            else
            {                                                   // else
                return RegionOutput(IF97Parameters.d, T, p, SatState.NONE);
            }
        }
Beispiel #9
0
 static double X_pQ(IF97Parameters inkey, double p, double Q)
 {
     double Xliq, Xvap;
     if ((p < Constants.Ptrip) || (p > Constants.Pcrit))
         throw new ArgumentOutOfRangeException("Pressure out of range");
     if ((Q < 0.0) || (Q > 1.0))
         throw new ArgumentOutOfRangeException("Quality out of range");
     switch (inkey)
     {
         case IF97Parameters.h:
         case IF97Parameters.s:
         case IF97Parameters.u:
             Xliq = RegionOutput(inkey, Tsat97(p), p, SatState.LIQUID);
             Xvap = RegionOutput(inkey, Tsat97(p), p, SatState.VAPOR);
             return Q * Xvap + (1 - Q) * Xliq;
         case IF97Parameters.d:
             Xliq = 1.0 / RegionOutput(IF97Parameters.d, Tsat97(p), p, SatState.LIQUID);
             Xvap = 1.0 / RegionOutput(IF97Parameters.d, Tsat97(p), p, SatState.VAPOR);
             return 1.0 / (Q * Xvap + (1 - Q) * Xliq);
         default:
             throw new ArgumentException("Mixture property undefined");
     }
 }
Beispiel #10
0
        public static double RegionOutput(IF97Parameters outkey, double T, double p, SatState State)
        {

            IF97REGIONS region = RegionDetermination_TP(T, p);

            switch (region)
            {
                case IF97REGIONS.REGION_1:
                    if (State == SatState.VAPOR)
                        return R2.output(outkey, T, p);  // On saturation curve and need the Vapor phase
                    else
                        return R1.output(outkey, T, p);  // otherwise, use Liquid Region 1
                case IF97REGIONS.REGION_2:
                    if (State == SatState.LIQUID)
                        return R1.output(outkey, T, p);  // On saturation curve and need the Liquid phase
                    else
                        return R2.output(outkey, T, p);  // otherwise, use Vapor Region 2
                case IF97REGIONS.REGION_3:
                    return Region3.output(outkey, T, p, State);
                case IF97REGIONS.REGION_4:
                    if (State == SatState.VAPOR)
                    {
                        return R2.output(outkey, T, p);
                    }
                    else if (State == SatState.LIQUID)
                    {
                        return R1.output(outkey, T, p);
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException("Cannot use Region 4 with T and p as inputs");
                    }
                case IF97REGIONS.REGION_5: return R5.output(outkey, T, p);
            }
            throw new ArgumentOutOfRangeException("Unable to match region");
        }