Пример #1
0
 // Calculate manages calculations that need to be run for each time step
 public void Calculate
 (
     double HGlo                                             // Horizontal Global Irradiance [W/m2]
     , double NExtra                                         // Extraterrestrial Normal Irradiance [W/m2]
     , double SunZenith                                      // The Zenith position of the sun with 0 being normal to the earth [radians]
 )
 {
     clearnessIndex = Sun.GetClearnessIndex(HGlo, NExtra, SunZenith);
     // Clearness correction is treated as a loss for consistency, but made negative so that it has the effect of a gain
     clearnessCorrection = -1 * Interpolate.Linear(ClearnessIndexArr, ClearnessCorrectionArr, clearnessIndex);
 }
Пример #2
0
        // Calculation method
        // There are 6 ways to call the Calculate method; for each, only some of the parameters are required to calculate global, beam and diffuse. The inputs can be
        // 1. global horizontal
        // 2. global horizontal and diffuse horizontal
        // 3. global horizontal and direct horizontal
        // 4. global horizontal and direct normal
        // 5. diffuse horizontal and direct horizontal
        // 6. diffuse horizontal and direct normal
        public void Calculate
        (
            double Zenith                   // zenith angle of sun [radians]
            , double _HGlo  = double.NaN    // global horizontal irradiance [W/m2]
            , double _HDif  = double.NaN    // diffuse horizontal irradiance [W/m2]
            , double _NDir  = double.NaN    // direct normal irradiance [W/m2]
            , double _HDir  = double.NaN    // direct horizontal irradiance [W/m2]
            , double NExtra = double.NaN    // normal extraterrestrial irradiance [W/m2]
        )
        {
            // Set all values to an invalid
            // Check that at least some of the radiation inputs are properly defined
            try
            {
                // Either HGlo has to be defined, or HDif and one of the two direct components
                if (double.IsNaN(_HGlo) && (double.IsNaN(_HDif) || (double.IsNaN(HDir) && double.IsNaN(NDir))))
                {
                    throw new CASSYSException("Splitter: insufficient number of inputs defined.");
                }

                // If global is defined, cannot have both diffuse and direct defined
                if (!double.IsNaN(_HGlo) && !double.IsNaN(_HDif) && ((!double.IsNaN(_HDir)) || !double.IsNaN(_NDir)))
                {
                    throw new CASSYSException("Splitter: cannot specify both diffuse and direct when global is used.");
                }

                // Cannot have direct normal and direct horizontal defined
                if (!double.IsNaN(_HDir) && !double.IsNaN(_NDir))
                {
                    throw new CASSYSException("Splitter: cannot specify both direct normal and direct horizontal.");
                }

                // If global is defined but neither diffuse and direct are defined,
                // then additional inputs are required to calculate them
                if (!double.IsNaN(_HGlo) && !double.IsNaN(_HDif) && !double.IsNaN(_HDir) && !double.IsNaN(_NDir))
                {
                    if (NExtra == double.NaN)
                    {
                        throw new CASSYSException("Splitter: Extraterrestrial irradiance is required when only global horizontal is specified.");
                    }
                }
            }
            catch (CASSYSException cs)
            {
                ErrorLogger.Log(cs, ErrLevel.FATAL);
            }

            // Calculate cos of zenith angle
            double cosZ = Math.Cos(Zenith);

            // First case: only global horizontal is defined
            // Calculate diffuse using the Hollands and Orgill correlation
            try
            {
                // If only HGlo is specified this case is used, first check the values provided in the program:
                if (!double.IsNaN(_HGlo) && double.IsNaN(_HDif) && double.IsNaN(_NDir) && double.IsNaN(_HDir))
                {
                    // Initialize value of HGlo
                    HGlo = _HGlo;

                    // If sun below horizon, direct is zero and diffuse is global
                    // Changed this to sun below 87.5° as high zenith angles sometimes caused problems of
                    // high direct on tilted surfaces
                    if (Zenith > 87.5 * DTOR || HGlo <= 0)
                    {
                        HDif = HGlo;
                        HDir = NDir = 0;
                    }

                    // Compute diffuse fraction
                    else
                    {
                        double kt = Sun.GetClearnessIndex(HGlo, NExtra, Zenith);
                        double kd = Sun.GetDiffuseFraction(kt);
                        kd = Math.Min(kd, 1.0);
                        kd = Math.Max(kd, 0.0);

                        // Compute diffuse and direct on horizontal
                        HDif = HGlo * kd;
                        HDir = HGlo - HDif;
                        NDir = HDir / cosZ;
                    }

                    // Limit beam normal to clear sky value
                    // ASHRAE clear sky model (ASHRAE Handbook - Fundamentals, 2013, ch. 14) with tau_b = 0.245, taud = 2.611, a_b = 0.668 and a_d = 0.227
                    // (these values are from Flagstaff, AZ, for the month of June, and lead to one of the highest beam/extraterrestrial ratios worldwide)
                    double AirMass = Astro.GetAirMass(Zenith);
                    double NDir_cs = NExtra * Math.Exp(-0.245 * Math.Pow(AirMass, 0.668));
                    NDir = Math.Min(NDir, NDir_cs);
                    HDir = NDir * cosZ;
                    HDif = HGlo - HDir;
                }

                // Second case: global horizontal and diffuse horizontal are defined then this
                else if (_HGlo != double.NaN && _HDif != double.NaN)
                {
                    // If sun below horizon, direct is zero and diffuse is global
                    // Changed this to sun below 87.5° as high zenith angles sometimes caused problems of
                    // high direct on tilted surfaces
                    if (Zenith > 87.5 * DTOR || _HGlo <= 0)
                    {
                        HGlo = _HGlo;
                        HDif = _HGlo;
                        HDir = NDir = 0;
                    }
                    else
                    {
                        HGlo = _HGlo;
                        HDif = Math.Min(_HGlo, _HDif);
                        HDir = HGlo - HDif;
                        NDir = HDir / cosZ;
                    }
                }

                // Third case: global horizontal and direct horizontal are defined
                else if (_HGlo != double.NaN && _HDir != double.NaN)
                {
                    HGlo = _HGlo;
                    HDir = Math.Min(_HGlo, _HDir);
                    HDif = HGlo - HDir;
                    NDir = HDir / cosZ;
                }

                // Fourth case: global horizontal and direct normal are defined
                else if (_HGlo != double.NaN && _NDir != double.NaN)
                {
                    HGlo = _HGlo;
                    HDir = Math.Min(HGlo, NDir * cosZ);
                    HDif = HGlo - HDir;
                    NDir = HDir / cosZ;
                }

                // Fifth case: diffuse horizontal and direct horizontal are defined
                else if (_HDif != double.NaN && _HDir != double.NaN)
                {
                    HDif = _HDif;
                    HDir = _HDir;
                    HGlo = HDif + HDir;
                    NDir = HDir / cosZ;
                }

                // Sixth case: diffuse horizontal and direct normal are defined
                else if (_HDif != double.NaN && _NDir != double.NaN)
                {
                    HDif = _HDif;
                    NDir = _NDir;
                    HDir = NDir * cosZ;
                    HGlo = HDif + HDir;
                }

                // Other cases: should never get there
                else
                {
                    throw new CASSYSException("Splitter: unexpected case encountered.");
                }
            }
            catch (CASSYSException ex)
            {
                ErrorLogger.Log(ex, ErrLevel.FATAL);
            }
        }