示例#1
0
        // De-transposition method to the be used if the meter and panel tilt do not match
        void PyranoDetranspose(SimMeteo SimMet)
        {
            if (pyranoTilter.NoPyranoAnglesDefined)
            {
                SimTracker.Calculate(SimSun.Zenith, SimSun.Azimuth, SimMet.Year, SimMet.DayOfYear);
                pyranoTilter.itsSurfaceAzimuth = SimTracker.SurfAzimuth;
                pyranoTilter.itsSurfaceSlope   = SimTracker.SurfSlope;
                pyranoTilter.IncidenceAngle    = SimTracker.IncidenceAngle;
            }

            // Lower bound of bisection
            double HGloLo = 0;

            // Higher bound of bisection
            double HGloHi = SimSun.NExtra;

            // Calculating the Incidence Angle for the current setup
            double cosInc = Tilt.GetCosIncidenceAngle(SimSun.Zenith, SimSun.Azimuth, pyranoTilter.itsSurfaceSlope, pyranoTilter.itsSurfaceAzimuth);

            // Trivial case
            if (SimMet.TGlo <= 0)
            {
                SimSplitter.Calculate(SimSun.Zenith, 0, NExtra: SimSun.NExtra);
                pyranoTilter.Calculate(SimSplitter.NDir, SimSplitter.HDif, SimSun.NExtra, SimSun.Zenith, SimSun.Azimuth, SimSun.AirMass, SimMet.MonthOfYear, SimMet.Albedo);
            }
            else if ((SimSun.Zenith > 87.5 * Util.DTOR) || (cosInc <= Math.Cos(87.5 * Util.DTOR)))
            {
                SimMet.HGlo = SimMet.TGlo / ((1 + Math.Cos(pyranoTilter.itsSurfaceSlope)) / 2 + pyranoTilter.itsMonthlyAlbedo[SimMet.MonthOfYear] * (1 - Math.Cos(pyranoTilter.itsSurfaceSlope)) / 2);

                // Forcing the horizontal irradiance to be composed entirely of diffuse irradiance
                SimSplitter.HGlo = SimMet.HGlo;
                SimSplitter.HDif = SimMet.HGlo;
                SimSplitter.NDir = 0;
                SimSplitter.HDir = 0;

                //SimSplitter.Calculate(SimSun.Zenith, HGlo, NExtra: SimSun.NExtra);
                pyranoTilter.Calculate(SimSplitter.NDir, SimSplitter.HDif, SimSun.NExtra, SimSun.Zenith, SimSun.Azimuth, SimSun.AirMass, SimMet.MonthOfYear, SimMet.Albedo);
            }
            // Otherwise, bisection loop
            else
            {
                // Bisection loop
                while (Math.Abs(HGloHi - HGloLo) > 0.01)
                {
                    // Use the central value between the domain to start the bisection, and then solve for TGlo,
                    double HGloAv = (HGloLo + HGloHi) / 2;
                    SimSplitter.Calculate(SimSun.Zenith, _HGlo: HGloAv, NExtra: SimSun.NExtra);
                    pyranoTilter.Calculate(SimSplitter.NDir, SimSplitter.HDif, SimSun.NExtra, SimSun.Zenith, SimSun.Azimuth, SimSun.AirMass, SimMet.MonthOfYear, SimMet.Albedo);
                    double TGloAv = pyranoTilter.TGlo;

                    // Compare the TGloAv calculated from the Horizontal guess to the acutal TGlo and change the bounds for analysis
                    // comparing the TGloAv and TGlo
                    if (TGloAv < SimMet.TGlo)
                    {
                        HGloLo = HGloAv;
                    }
                    else
                    {
                        HGloHi = HGloAv;
                    }
                }
            }

            SimMet.HGlo = SimSplitter.HGlo;

            // This value of the horizontal global should now be transposed to the tilt value from the array.
            Transpose(SimMet);
        }
示例#2
0
        // Calculate the tracker slope, azimuth and incidence angle using
        public void Calculate(double SunZenith, double SunAzimuth, int Year, int DayOfYear)
        {
            switch (itsTrackMode)
            {
            case TrackMode.SAXT:
                // Surface stays parallel to the ground.
                if (itsTrackerSlope == 0.0)
                {
                    // For east-west tracking, the absolute value of the sun-azimuth is checked against the tracker azimuth
                    // This is from Duffie and Beckman Page 22.
                    if (itsTrackerAzimuth == Math.PI / 2 || itsTrackerAzimuth == -Math.PI / 2)
                    {
                        // If the user inputs a minimum tilt less than 0, the tracker is able to face the non-dominant direction, so the surface azimuth will change based on the sun azimuth.
                        // However, if the minimum tilt is greater than zero, the tracker can only face the dominant direction.
                        if (itsMinTilt <= 0)
                        {
                            // Math.Abs is used so that the surface azimuth is set to 0 degrees if the sun azimuth is between -90 and 90, and set to 180 degrees if the sun azimuth is between -180 and -90 or between 90 and 180
                            if (Math.Abs(SunAzimuth) >= Math.Abs(itsTrackerAzimuth))
                            {
                                SurfAzimuth = Math.PI;
                            }
                            else
                            {
                                SurfAzimuth = 0;
                            }
                        }
                        else
                        {
                            SurfAzimuth = itsTrackerAzimuth - Math.PI / 2;
                        }
                    }
                    else if (itsTrackerAzimuth == 0)
                    {
                        // For north-south tracking, the sign of the sun-azimuth is checked against the tracker azimuth
                        // This is from Duffie and Beckman Page 22.
                        if (SunAzimuth >= itsTrackerAzimuth)
                        {
                            SurfAzimuth = Math.PI / 2;
                        }
                        else
                        {
                            SurfAzimuth = -Math.PI / 2;
                        }
                    }

                    // Surface slope calculated from eq. 31 of reference guide
                    SurfSlope = Math.Atan2(Math.Sin(SunZenith) * Math.Cos(SurfAzimuth - SunAzimuth), Math.Cos(SunZenith));

                    // If the shadow is greater than the Pitch and backtracking is selected
                    if (useBackTracking)
                    {
                        if (itsTrackerBW / (Math.Cos(SurfSlope)) > itsTrackerPitch)
                        {
                            // NB: From Lorenzo, Narvarte, and Munoz
                            AngleCorrection = Math.Acos((itsTrackerPitch * (Math.Cos(SurfSlope))) / itsTrackerBW);
                            SurfSlope       = SurfSlope - AngleCorrection;
                        }
                    }

                    // Adjusting limits for elevation tracking, so if positive min tilt, the tracker operates within limits properly
                    if (itsTrackerAzimuth == Math.PI / 2 || itsTrackerAzimuth == -Math.PI / 2)
                    {
                        if (itsMinTilt <= 0)
                        {
                            if (Math.Abs(SunAzimuth) <= itsTrackerAzimuth)
                            {
                                SurfSlope = Math.Min(itsMaxTilt, SurfSlope);
                            }
                            else if (Math.Abs(SunAzimuth) > itsTrackerAzimuth)
                            {
                                SurfSlope = Math.Min(Math.Abs(itsMinTilt), SurfSlope);
                            }
                        }

                        else if (itsMinTilt > 0)
                        {
                            SurfSlope = Math.Min(SurfSlope, itsMaxTilt);
                            SurfSlope = Math.Max(SurfSlope, itsMinTilt);
                        }
                    }

                    else if (itsTrackerAzimuth == 0)
                    {
                        SurfSlope = Math.Min(itsMaxTilt, SurfSlope);
                    }
                }
                else
                {
                    // Tilt and Roll
                    double aux = Tilt.GetCosIncidenceAngle(SunZenith, SunAzimuth, itsTrackerSlope, itsTrackerAzimuth);
                    // Equation (7) from Marion and Dobos
                    RotAngle = Math.Atan2((Math.Sin(SunZenith) * Math.Sin(SunAzimuth - itsTrackerAzimuth)), aux);

                    //NB: enforcing rotation limits on tracker
                    RotAngle = Math.Min(itsMaxRotationAngle, RotAngle);
                    RotAngle = Math.Max(itsMinRotationAngle, RotAngle);


                    // Slope from equation (1) in Marion and Dobos
                    SurfSlope = Math.Acos(Math.Cos(RotAngle) * Math.Cos(itsTrackerSlope));

                    // Surface Azimuth from NREL paper
                    if (SurfSlope != 0)
                    {
                        // Equation (3) in Marion and Dobos
                        if ((-Math.PI <= RotAngle) && (RotAngle < -Math.PI / 2))
                        {
                            SurfAzimuth = itsTrackerAzimuth - Math.Asin(Math.Sin(RotAngle) / Math.Sin(SurfSlope)) - Math.PI;
                        }
                        // Equation (4) in Marion and Dobos
                        else if ((Math.PI / 2 < RotAngle) && (RotAngle <= Math.PI))
                        {
                            SurfAzimuth = itsTrackerAzimuth - Math.Asin(Math.Sin(RotAngle) / Math.Sin(SurfSlope)) + Math.PI;
                        }
                        // Equation (2) in Marion and Dobos
                        else
                        {
                            SurfAzimuth = itsTrackerAzimuth + Math.Asin(Math.Sin(RotAngle) / Math.Sin(SurfSlope));
                        }
                    }
                    //NB: 360 degree correction to put Surface Azimuth into the correct quadrant, see Note 1
                    if (SurfAzimuth > Math.PI)
                    {
                        SurfAzimuth -= (Math.PI) * 2;
                    }
                    else if (SurfAzimuth < -Math.PI)
                    {
                        SurfAzimuth += (Math.PI) * 2;
                    }
                }
                break;

            // Two Axis Tracking
            case TrackMode.TAXT:
                // Defining the surface slope
                SurfSlope = SunZenith;
                SurfSlope = Math.Max(itsMinTilt, SurfSlope);
                SurfSlope = Math.Min(itsMaxTilt, SurfSlope);

                // Defining the surface azimuth
                SurfAzimuth = SunAzimuth;

                // Changes the reference frame to be with respect to the reference azimuth
                if (SurfAzimuth >= 0)
                {
                    SurfAzimuth -= itsAzimuthRef;
                }
                else
                {
                    SurfAzimuth += itsAzimuthRef;
                }

                // Enforcing the rotation limits with respect to the reference azimuth
                SurfAzimuth = Math.Max(itsMinAzimuth, SurfAzimuth);
                SurfAzimuth = Math.Min(itsMaxAzimuth, SurfAzimuth);

                // Moving the surface azimuth back into the azimuth variable convention
                if (SurfAzimuth >= 0)
                {
                    SurfAzimuth -= itsAzimuthRef;
                }

                else
                {
                    SurfAzimuth += itsAzimuthRef;
                }
                break;

            // Azimuth Vertical Axis Tracking
            case TrackMode.AVAT:
                // Slope is constant.
                // Defining the surface azimuth
                SurfAzimuth = SunAzimuth;

                // Changes the reference frame to be with respect to the reference azimuth
                if (SurfAzimuth >= 0)
                {
                    SurfAzimuth -= itsAzimuthRef;
                }
                else
                {
                    SurfAzimuth += itsAzimuthRef;
                }

                // Enforcing the rotation limits with respect to the reference azimuth
                SurfAzimuth = Math.Max(itsMinAzimuth, SurfAzimuth);
                SurfAzimuth = Math.Min(itsMaxAzimuth, SurfAzimuth);

                // Moving the surface azimuth back into the azimuth variable convention
                if (SurfAzimuth >= 0)
                {
                    SurfAzimuth -= itsAzimuthRef;
                }

                else
                {
                    SurfAzimuth += itsAzimuthRef;
                }

                break;

            // Fixed Tilt with Seasonal Adjustment
            // determining if the current timestamp is in the summer or winter season and setting SurfSlope accordingly
            case TrackMode.FTSA:
                // SummerDate and WinterDate must be recalculated if year changes due to possible leap year
                if (previousYear != Year)
                {
                    SummerDate = new DateTime(Year, itsSummerMonth, itsSummerDay);
                    WinterDate = new DateTime(Year, itsWinterMonth, itsWinterDay);
                }
                previousYear = Year;

                // Winter date is before summer date in calender year
                if (SummerDate.DayOfYear - WinterDate.DayOfYear > 0)
                {
                    if (DayOfYear >= WinterDate.DayOfYear && DayOfYear < SummerDate.DayOfYear)
                    {
                        SurfSlope = itsPlaneTiltWinter;
                    }
                    else
                    {
                        SurfSlope = itsPlaneTiltSummer;
                    }
                }
                // Summer date is before winter date in calender year
                else
                {
                    if (DayOfYear >= SummerDate.DayOfYear && DayOfYear < WinterDate.DayOfYear)
                    {
                        SurfSlope = itsPlaneTiltSummer;
                    }
                    else
                    {
                        SurfSlope = itsPlaneTiltWinter;
                    }
                }
                break;

            case TrackMode.NOAT:
                break;

            // Throw error to user if there is an issue with the tracker.
            default:
                ErrorLogger.Log("Tracking Parameters were incorrectly defined. Please check your input file.", ErrLevel.FATAL);
                break;
            }

            IncidenceAngle = Tilt.GetIncidenceAngle(SunZenith, SunAzimuth, SurfSlope, SurfAzimuth);
        }