Esempio n. 1
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);
            }
        }
Esempio n. 2
0
        // Calculation for inverter output power, using efficiency curve
        public void Calculate
        (
            int DayOfYear                             // Day of year (1-365)
            , double Hour                             // Hour of day, in decimal format (11.75 = 11:45 a.m.)
        )
        {
            double itsSLatR  = Utilities.ConvertDtoR(itsSLat);
            double itsSLongR = Utilities.ConvertDtoR(itsSLong);
            double itsMLongR = Utilities.ConvertDtoR(itsMLong);

            try
            {
                if (DayOfYear < 1 || DayOfYear > 365 || Hour < 0 || Hour > 24)
                {
                    throw new CASSYSException("Sun.Calculate: Invalid time stamp for sun position calculation");
                }
            }
            catch (CASSYSException cs)
            {
                ErrorLogger.Log(cs, ErrLevel.FATAL);
            }

            // Compute declination and normal extraterrestrial Irradiance if day has changed
            // Compute Sunrise and Sunset hour angles
            if (DayOfYear != itsCurrentDayOfYear)
            {
                itsCurrentDayOfYear = DayOfYear;
                itsCurrentDecl      = Astro.GetDeclination(itsCurrentDayOfYear);
                itsCurrentNExtra    = Astro.GetNormExtra(itsCurrentDayOfYear);

                // Variables used to hold the apparent/true sunset and sunrise hour angles
                double appSunRiseHA;                        // Hour angle for Sunrise [radians]
                double appSunsetHA;                         // Hour angle for Sunset  [radians]
                double trueSunsetHA;                        // True Sunset Hour angle [radians]

                // Invoking the Tilt method to get the values
                Tilt.CalcApparentSunsetHourAngle(itsSLatR, itsCurrentDecl, itsSurfaceSlope, Azimuth, out appSunRiseHA, out appSunsetHA, out trueSunsetHA);

                // Assigning to the output values
                AppSunriseHour  = Math.Abs(appSunRiseHA) * Util.HAtoR;
                AppSunsetHour   = Util.NoonHour + appSunsetHA * Util.HAtoR;
                TrueSunSetHour  = Util.NoonHour + trueSunsetHA * Util.HAtoR;
                TrueSunRiseHour = TrueSunSetHour - Astro.GetDayLength(itsSLatR, itsCurrentDecl);

                // If using local standard time then modify the sunrise and sunset to match the local time stamp.
                if (itsLSTFlag)
                {
                    TrueSunSetHour -= Astro.GetATmsST(DayOfYear, itsSLongR, itsMLongR) / 60; // Going from solar to local time
                    TrueSunRiseHour = TrueSunSetHour - Astro.GetDayLength(itsSLatR, itsCurrentDecl);
                }
            }

            // Compute hour angle
            double SolarTime = Hour;

            if (itsLSTFlag)
            {
                SolarTime += Astro.GetATmsST(DayOfYear, itsSLongR, itsMLongR) / 60; // Going from local to solar time
            }

            double HourAngle = Astro.GetHourAngle(SolarTime);

            // Compute azimuth and zenith angles
            Astro.CalcSunPositionHourAngle(itsCurrentDecl, HourAngle, itsSLatR, out Zenith, out Azimuth);

            // Compute normal extraterrestrial Irradiance
            NExtra = itsCurrentNExtra;

            // Compute air mass
            AirMass = Astro.GetAirMass(Zenith);
        }