Пример #1
0
        // Transposition of the global horizontal irradiance values to the transposed values
        void Transpose(SimMeteo SimMet)
        {
            SimSun.Calculate(SimMet.DayOfYear, HourOfDay);

            // Calculating the Surface Slope and Azimuth based on the Tracker Chosen
            SimTracker.Calculate(SimSun.Zenith, SimSun.Azimuth, SimMet.Year, SimMet.DayOfYear);
            SimTilter.itsSurfaceSlope           = SimTracker.SurfSlope;
            SimTilter.itsSurfaceAzimuth         = SimTracker.SurfAzimuth;
            SimTilterOpposite.itsSurfaceSlope   = Math.PI - SimTracker.SurfSlope;
            SimTilterOpposite.itsSurfaceAzimuth = Math.PI + SimTracker.SurfAzimuth;

            if (double.IsNaN(SimMet.HDiff))
            {
                // Split global into direct
                SimSplitter.Calculate(SimSun.Zenith, SimMet.HGlo, NExtra: SimSun.NExtra);
            }
            else
            {
                // Split global into direct and diffuse
                SimSplitter.Calculate(SimSun.Zenith, SimMet.HGlo, _HDif: SimMet.HDiff, NExtra: SimSun.NExtra);
            }

            // Calculate tilted irradiance
            SimTilter.Calculate(SimSplitter.NDir, SimSplitter.HDif, SimSun.NExtra, SimSun.Zenith, SimSun.Azimuth, SimSun.AirMass, SimMet.MonthOfYear, SimMet.Albedo);
            SimTilterOpposite.Calculate(SimSplitter.NDir, SimSplitter.HDif, SimSun.NExtra, SimSun.Zenith, SimSun.Azimuth, SimSun.AirMass, SimMet.MonthOfYear, SimMet.Albedo);
        }
Пример #2
0
        // Calculates AC power of system
        public void Calculate
        (
            SimMeteo SimMet                          // Meteological data required for ACPower calculation
        )
        {
            // Initializing to default
            ACPower = double.NaN;

            // Log errors if incorrect parameters are found
            // No check is made for radiation as it can be negative at night in some cases
            if (SimMet.MonthOfYear < 1 || SimMet.MonthOfYear > 12)
            {
                ErrorLogger.Log("ASTM E2848 Calculate: Month must be betwen 1 and 12", ErrLevel.WARNING);
            }
            else if (SimMet.TAmbient < -273.15)
            {
                ErrorLogger.Log("ASTM E2848 Calculate: Ambient temperature must be greater than 0K.", ErrLevel.WARNING);
            }
            else if (SimMet.WindSpeed < 0)
            {
                ErrorLogger.Log("ASTM E2848 Calculate: Windspeed must be greater than 0 m/s.", ErrLevel.WARNING);
            }
            else
            {
                // If inputs are valid continue with power calculation using the ASTM E2848 Equation (Ref 1)
                ACPower = Math.Min(SimMet.TGlo * (itsA1 + itsA2 * SimMet.TGlo + itsA3 * SimMet.TAmbient + itsA4 * SimMet.WindSpeed) * itsEAF[SimMet.MonthOfYear - 1], itsPmax);
                ACPower = Math.Max(ACPower, 0);
            }

            // Assigning Outputs for this class.
            AssignOutputs();
        }
Пример #3
0
        public void Calculate
        (
            SimMeteo SimMet                                               // Meteological data from inputfile
        )
        {
            // Calculating Sun position
            // Calculate the Solar Azimuth, and Zenith angles [radians]
            SimSun.itsSurfaceSlope = SimTracker.SurfSlope;
            SimSun.Calculate(SimMet.DayOfYear, SimMet.HourOfDay);

            HourOfDay = SimMet.HourOfDay;

            // The time stamp must be adjusted for sunset and sunrise hours such that the position of the sun is only calculated
            // for the middle of the interval where the sun is above the horizon.
            if ((SimMet.TimeStepEnd > SimSun.TrueSunSetHour) && (SimMet.TimeStepBeg < SimSun.TrueSunSetHour))
            {
                HourOfDay = SimMet.TimeStepBeg + (SimSun.TrueSunSetHour - SimMet.TimeStepBeg) / 2;
            }
            else if ((SimMet.TimeStepBeg < SimSun.TrueSunRiseHour) && (SimMet.TimeStepEnd > SimSun.TrueSunRiseHour))
            {
                HourOfDay = SimSun.TrueSunRiseHour + (SimMet.TimeStepEnd - SimSun.TrueSunRiseHour) / 2;
            }

            // Based on the definition of Input file, use Tilted irradiance or transpose the horizontal irradiance
            if (ReadFarmSettings.UsePOA == true)
            {
                // Check if the meter tilt and surface tilt are equal, if not detranspose the pyranometer
                if (string.Compare(ReadFarmSettings.CASSYSCSYXVersion, "0.9.2") >= 0)
                {
                    // Checking if the Meter and Panel Tilt are different:
                    if ((pyranoTilter.itsSurfaceAzimuth != SimTracker.SurfAzimuth) || (pyranoTilter.itsSurfaceSlope != SimTracker.SurfSlope))
                    {
                        if (SimMet.TGlo < 0)
                        {
                            SimMet.TGlo = 0;

                            if (negativeIrradFlag == false)
                            {
                                ErrorLogger.Log("Global Plane of Array Irradiance contains negative values. CASSYS will set the value to 0.", ErrLevel.WARNING);
                                negativeIrradFlag = true;
                            }
                        }
                        PyranoDetranspose(SimMet);
                    }
                    else
                    {
                        if (SimMet.TGlo < 0)
                        {
                            SimMet.TGlo = 0;

                            if (negativeIrradFlag == false)
                            {
                                ErrorLogger.Log("Global Plane of Array Irradiance contains negative values. CASSYS will set the value to 0.", ErrLevel.WARNING);
                                negativeIrradFlag = true;
                            }
                        }
                        Detranspose(SimMet);
                    }
                }
                else
                {
                    if (SimMet.TGlo < 0)
                    {
                        SimMet.TGlo = 0;

                        if (negativeIrradFlag == false)
                        {
                            ErrorLogger.Log("Global Plane of Array Irradiance contains negative values. CASSYS will the value to 0.", ErrLevel.WARNING);
                            negativeIrradFlag = true;
                        }
                    }
                    Detranspose(SimMet);
                }
            }
            else
            {
                if (SimMet.HGlo < 0)
                {
                    SimMet.HGlo = 0;

                    if (negativeIrradFlag == false)
                    {
                        ErrorLogger.Log("Global Horizontal Irradiance is negative. CASSYS set the value to 0.", ErrLevel.WARNING);
                        negativeIrradFlag = true;
                    }
                }
                if (ReadFarmSettings.UseDiffMeasured == true)
                {
                    if (SimMet.HDiff < 0)
                    {
                        if (negativeIrradFlag == false)
                        {
                            SimMet.HDiff = 0;
                            ErrorLogger.Log("Horizontal Diffuse Irradiance is negative. CASSYS set the value to 0.", ErrLevel.WARNING);
                            negativeIrradFlag = true;
                        }
                    }
                }
                else
                {
                    SimMet.HDiff = double.NaN;
                }

                Transpose(SimMet);
            }
            // Calculate horizon shading effects
            SimHorizonShading.Calculate(SimSun.Zenith, SimSun.Azimuth, SimTracker.SurfSlope, SimTracker.SurfAzimuth, SimTilter.TDir, SimTilter.TDif, SimTilter.TRef, SimSplitter.HDir, SimSplitter.HDif, SimTracker.itsTrackMode);

            // Assigning outputs
            AssignOutputs();
        }
Пример #4
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);
        }
Пример #5
0
        // Gets the day of the year based on a given date
        public static void TSBreak(String TimeStamp, out int dayOfYear, out double hour, out int year, out int month, out double nextTimeStampHour, out double baseTimeStampHour, SimMeteo simMeteoParser)
        {
            try
            {
                CurrentTimeStamp = DateTime.ParseExact(TimeStamp, Util.timeFormat, null);

                // Checks ensure the time series is always progressing forward.
                if (ErrorLogger.iterationCount != 1)
                {
                    if (CurrentTimeStamp != cachedTimeStamp)
                    {
                        // Check if the time stamps are going back in time
                        if (DateTime.Compare(CurrentTimeStamp, cachedTimeStamp) < 0)
                        {
                            ErrorLogger.Log("Time stamps in the Input File go backwards in time. Please check your input file. CASSYS has ended.", ErrLevel.FATAL);
                        }
                    }
                }
                else
                {
                    // Get the next expected time stamp
                    cachedTimeStamp = CurrentTimeStamp;
                }

                // Next and Base time stamps are used to check if the sun-rise and sun-set event occurs in between the time stamps under consideration
                DateTime nextTimeStamp = DateTime.ParseExact(TimeStamp, Util.timeFormat, null);
                DateTime baseTimeStamp = DateTime.ParseExact(TimeStamp, Util.timeFormat, null);

                switch (Util.AveragedAt)
                {
                case "Beginning":
                    baseTimeStamp    = CurrentTimeStamp;
                    nextTimeStamp    = baseTimeStamp.AddMinutes(Util.timeStep);
                    CurrentTimeStamp = CurrentTimeStamp.AddMinutes(Util.timeStep / 2D);

                    break;

                case "End":
                    nextTimeStamp    = CurrentTimeStamp;
                    baseTimeStamp    = CurrentTimeStamp.AddMinutes(-Util.timeStep);
                    CurrentTimeStamp = CurrentTimeStamp.AddMinutes(-Util.timeStep / 2D);
                    break;

                default:
                    baseTimeStamp    = CurrentTimeStamp.AddMinutes(-Util.timeStep / 2D);
                    nextTimeStamp    = CurrentTimeStamp.AddMinutes(Util.timeStep / 2D);
                    CurrentTimeStamp = CurrentTimeStamp.AddMinutes(0);
                    break;
                }

                dayOfYear = CurrentTimeStamp.DayOfYear;

                // Allowing for Leap Years - Assumes February 29 as Feb 28 and all other days as their day number during a normal year
                if ((CurrentTimeStamp.Month > 2) && (DateTime.IsLeapYear(CurrentTimeStamp.Year)))
                {
                    if (dayOfYear > 59)
                    {
                        dayOfYear = CurrentTimeStamp.DayOfYear - 1;
                    }
                }
                hour  = CurrentTimeStamp.Hour + CurrentTimeStamp.Minute / 60D + CurrentTimeStamp.Second / 3600D;
                year  = CurrentTimeStamp.Year;
                month = CurrentTimeStamp.Month;

                baseTimeStampHour = baseTimeStamp.Hour + baseTimeStamp.Minute / 60D + baseTimeStamp.Second / 3600D;
                nextTimeStampHour = nextTimeStamp.Hour + nextTimeStamp.Minute / 60D + nextTimeStamp.Second / 3600D;
            }
            catch (FormatException)
            {
                dayOfYear         = 0;
                hour              = 0;
                year              = 0;
                month             = 0;
                baseTimeStampHour = 0;
                nextTimeStampHour = 0;
                ErrorLogger.Log(TimeStamp + " was not recognized a valid DateTime. The date-time was expected in " + Util.timeFormat + " format. Please check Site definition file. Row was skipped", ErrLevel.WARNING);
                simMeteoParser.inputRead = false;
            }
        }
Пример #6
0
        double farmACMinVoltageLoss = 0;                        // Loss of power when voltage of the array is too small and forces the inverters to 'shut off' and when inverter is not operating at MPP [W]

        // Calculate method
        public void Calculate(
            RadiationProc RadProc,                              // Radiation related data
            SimMeteo SimMet                                     // Meteological data from inputfile
            )
        {
            // Reset Losses
            for (int i = 0; i < SimPVA.Length; i++)
            {
                SimInv[i].LossPMinThreshold = 0;
                SimInv[i].LossClipping      = 0;
                SimInv[i].LossLowVoltage    = 0;
                SimInv[i].LossHighVoltage   = 0;
            }

            // Calculating solar panel shading
            SimShading.Calculate(RadProc.SimSun.Zenith, RadProc.SimSun.Azimuth, RadProc.SimHorizonShading.TDir, RadProc.SimHorizonShading.TDif, RadProc.SimHorizonShading.TRef, RadProc.SimTracker.SurfSlope, RadProc.SimTracker.SurfAzimuth);

            // Calculating spectral model effects
            SimSpectral.Calculate(SimMet.HGlo, RadProc.SimSun.NExtra, RadProc.SimSun.Zenith);

            try
            {
                // Calculate PV Array Output for inputs read in this loop
                for (int j = 0; j < ReadFarmSettings.SubArrayCount; j++)
                {
                    // Adjust the IV Curve based on based on Temperature and Irradiance
                    SimPVA[j].CalcIVCurveParameters(SimMet.TGlo, SimShading.ShadTDir, SimShading.ShadTDif, SimShading.ShadTRef, RadProc.SimTilter.IncidenceAngle, SimMet.TAmbient, SimMet.WindSpeed, SimMet.TModMeasured, SimMet.MonthOfYear, SimSpectral.clearnessCorrection);

                    // Check Inverter status to determine if the Inverter is ON or OFF
                    GetInverterStatus(j);

                    // If inverter is off set appropriate variables to 0 and recalculate array in open circuit voltage
                    if (!SimInv[j].isON)
                    {
                        SimInv[j].ACPwrOut = 0;
                        SimInv[j].IOut     = 0;
                        SimPVA[j].CalcAtOpenCircuit();
                        SimPVA[j].Calculate(false, SimPVA[j].Voc);
                    }

                    //performing AC wiring calculations
                    SimACWiring[j].Calculate(SimInv[j]);

                    // Assigning the outputs to the dictionary
                    ReadFarmSettings.Outputlist["SubArray_Current" + (j + 1).ToString()]     = SimPVA[j].IOut;
                    ReadFarmSettings.Outputlist["SubArray_Voltage" + (j + 1).ToString()]     = SimPVA[j].VOut;
                    ReadFarmSettings.Outputlist["SubArray_Power" + (j + 1).ToString()]       = SimPVA[j].POut / 1000;
                    ReadFarmSettings.Outputlist["SubArray_Current_Inv" + (j + 1).ToString()] = SimInv[j].IOut;
                    ReadFarmSettings.Outputlist["SubArray_Voltage_Inv" + (j + 1).ToString()] = SimInv[j].itsOutputVoltage;
                    ReadFarmSettings.Outputlist["SubArray_Power_Inv" + (j + 1).ToString()]   = SimInv[j].ACPwrOut / 1000;
                }

                //Calculating total farm output and total ohmic loss
                farmACOutput    = 0;
                farmACOhmicLoss = 0;
                for (int i = 0; i < SimInv.Length; i++)
                {
                    farmACOutput    += SimInv[i].ACPwrOut;
                    farmACOhmicLoss += SimACWiring[i].ACWiringLoss;
                }

                SimTransformer.Calculate(farmACOutput - farmACOhmicLoss);

                // Calculating outputs that will be assigned for this interval
                // Shading each component of the Tilted radiaton
                // Using horizon affected tilted radiation
                ShadGloLoss   = (RadProc.SimTilter.TGlo - SimShading.ShadTGlo) - RadProc.SimHorizonShading.LossGlo;
                ShadGloFactor = (RadProc.SimTilter.TGlo > 0 ? SimShading.ShadTGlo / RadProc.SimTilter.TGlo : 1);
                ShadBeamLoss  = RadProc.SimHorizonShading.TDir - SimShading.ShadTDir;
                ShadDiffLoss  = RadProc.SimTilter.TDif > 0 ? RadProc.SimHorizonShading.TDif - SimShading.ShadTDif : 0;
                ShadRefLoss   = RadProc.SimTilter.TRef > 0 ? RadProc.SimHorizonShading.TRef - SimShading.ShadTRef : 0;

                //Calculating total farm level variables. Cleaning them so they are non-cumulative.
                farmDC                  = 0;
                farmDCCurrent           = 0;
                farmDCMismatchLoss      = 0;
                farmDCModuleQualityLoss = 0;
                farmDCOhmicLoss         = 0;
                farmDCSoilingLoss       = 0;
                farmDCTemp              = 0;
                farmTotalModules        = 0;
                farmPNomDC              = 0;
                farmPNomAC              = 0;
                farmACPMinThreshLoss    = 0;
                farmACClippingPower     = 0;
                farmACMaxVoltageLoss    = 0;
                farmACMinVoltageLoss    = 0;
                farmPnom                = 0;
                farmTempLoss            = 0;
                farmRadLoss             = 0;

                for (int i = 0; i < SimPVA.Length; i++)
                {
                    farmDC                  += SimPVA[i].POut;
                    farmDCCurrent           += SimPVA[i].IOut;
                    farmDCMismatchLoss      += Math.Max(0, SimPVA[i].MismatchLoss);
                    farmDCModuleQualityLoss += SimPVA[i].ModuleQualityLoss;
                    farmDCOhmicLoss         += SimPVA[i].OhmicLosses;
                    farmDCSoilingLoss       += SimPVA[i].SoilingLoss;
                    farmDCTemp              += SimPVA[i].TModule * SimPVA[i].itsNumModules;
                    farmTotalModules        += SimPVA[i].itsNumModules;
                    farmPNomDC              += SimPVA[i].itsPNomDCArray;
                    farmPNomAC              += SimInv[i].itsPNomArrayAC;
                    farmACPMinThreshLoss    += SimInv[i].LossPMinThreshold;
                    farmACClippingPower     += SimInv[i].LossClipping;
                    farmACMaxVoltageLoss    += SimInv[i].LossHighVoltage;
                    farmACMinVoltageLoss    += SimInv[i].LossLowVoltage;
                    farmPnom                += (SimPVA[i].itsPNom * SimPVA[i].itsNumModules) * SimPVA[i].TGloEff / 1000;
                    farmTempLoss            += SimPVA[i].tempLoss;
                    farmRadLoss             += SimPVA[i].radLoss;
                }

                // Averages all PV Array temperature values
                farmDCTemp /= farmTotalModules;
                farmModuleTempAndAmbientTempDiff = farmDCTemp - SimMet.TAmbient;
                farmDCEfficiency = (RadProc.SimTilter.TGlo > 0 ? farmDC / (RadProc.SimTilter.TGlo * farmArea) : 0) * 100;
                farmPNomDC       = Utilities.ConvertWtokW(farmPNomDC);
                farmPNomAC       = Utilities.ConvertWtokW(farmPNomAC);

                farmOverAllEff = (RadProc.SimTilter.TGlo > 0 && SimTransformer.POut > 0 ? SimTransformer.POut / (RadProc.SimTilter.TGlo * farmArea) : 0) * 100;
                farmPR         = RadProc.SimTilter.TGlo > 0 && farmPNomDC > 0 && SimTransformer.POut > 0 ? SimTransformer.POut / RadProc.SimTilter.TGlo / farmPNomDC : 0;
                farmSysIER     = (SimTransformer.itsPNom - SimTransformer.POut) / (RadProc.SimTilter.TGlo * 1000);
            }
            catch (Exception ce)
            {
                ErrorLogger.Log(ce, ErrLevel.FATAL);
            }

            // Assigning Outputs for this class.
            AssignOutputs();
        }
Пример #7
0
        // Method to start the simulation software run.
        public void Simulate(XmlDocument SiteSettings, String _Input = null, String _Output = null)
        {
            // Adding timer to calculate elapsed time for the simulation.
            Stopwatch timeTaken = new Stopwatch();

            timeTaken.Start();

            // Delete error log just before simulation
            if (File.Exists(Application.StartupPath + "/ErrorLog.txt"))
            {
                File.Delete(Application.StartupPath + "/ErrorLog.txt");
            }

            // ReadFarmSettings reads the overall configuration of the farm
            ReadFarmSettings.doc = SiteSettings;

            // Obtain IO File names, either from the command prompt, or from .CSYX
            if ((_Input == null) && (_Output == null))
            {
                ReadFarmSettings.AssignIOFileNames();
            }
            else
            {
                ReadFarmSettings.SimInputFile  = _Input;
                ReadFarmSettings.SimOutputFile = _Output;
            }

            // Collecting input and output file locations and Input/Output file location
            ReadFarmSettings.GetSimulationMode();

            // Inform user about site configuration:
            Console.WriteLine("Status: Configuring parameters");

            // Creating the SimMeteo Object to process the input file, and streamWriter to Write to the Output File
            try
            {
                // Reading and assigning the input file schema before configuring the inputs
                ReadFarmSettings.AssignInputFileSchema();

                // Instantiating the relevant simulation class based on the simulation mode
                switch (ReadFarmSettings.SystemMode)
                {
                case "ASTME2848Regression":
                    SimASTM = new ASTME2848();
                    SimASTM.Config();
                    break;

                case "GridConnected":
                    // Assign the Sub-Array Count for grid connected systems.
                    ReadFarmSettings.AssignSubArrayCount();
                    SimGridSys = new GridConnectedSystem();
                    SimGridSys.Config();
                    goto case "Radiation";

                case "Radiation":
                    SimRadProc = new RadiationProc();
                    SimRadProc.Config();
                    break;

                default:
                    ErrorLogger.Log("Invalid Simulation mode found. CASSYS will exit.", ErrLevel.FATAL);
                    break;
                }

                // Reading and assigning the input file schema and the output file schema
                ReadFarmSettings.AssignOutputFileSchema();

                // Notifying user of the Configuration status
                if (ErrorLogger.numWarnings == 0)
                {
                    Console.WriteLine("Status: Configuration OK.");
                }
                else
                {
                    Console.WriteLine("Status: There were problems encountered during configuration.");
                    Console.WriteLine("        Please see the error log file for details.");
                    Console.WriteLine("        CASSYS has configured parameters with default values.");
                }

                try
                {
                    // Read through the input file and perform calculations
                    Console.Write("Status: Simulation Running");

                    // Creating the input file parser
                    SimMeteo SimMeteoParser = new SimMeteo();
                    SimMeteoParser.Config();

                    // Create StreamWriter
                    if (ReadFarmSettings.outputMode == "str")
                    {
                        // Assigning Headers to output String
                        OutputString = ReadFarmSettings.OutputHeader.TrimEnd(',') + '\n';
                    }
                    // Create StreamWriter and write output to .csv file
                    else if (ReadFarmSettings.outputMode == "csv")
                    {
                        // If in batch mode, use the appending overload of StreamWriter
                        if ((File.Exists(ReadFarmSettings.SimOutputFile)) && (ReadFarmSettings.batchMode))
                        {
                            OutputFileWriter = new StreamWriter(ReadFarmSettings.SimOutputFile, true);
                        }
                        else
                        {
                            // Writing the headers to the new output file.
                            OutputFileWriter = new StreamWriter(ReadFarmSettings.SimOutputFile);

                            // Writing the headers to the new output file.
                            OutputFileWriter.WriteLine(ReadFarmSettings.OutputHeader);
                        }
                    }
                    // The following is executed if using iterative mode
                    else
                    {
                        // Row for output header created only during first simulation run
                        if (ReadFarmSettings.runNumber == 1)
                        {
                            ReadFarmSettings.outputTable.Rows.InsertAt(ReadFarmSettings.outputTable.NewRow(), 0);
                        }

                        // Placing output header in data table
                        ReadFarmSettings.outputTable.Rows[0][ReadFarmSettings.runNumber - 1] = ReadFarmSettings.OutputHeader.TrimEnd(',');
                    }

                    // Read through the Input File and perform the relevant simulation
                    while (!SimMeteoParser.InputFileReader.EndOfData)
                    {
                        SimMeteoParser.Calculate();

                        // If input file line could not be read, go to next line
                        if (!SimMeteoParser.inputRead)
                        {
                            continue;
                        }

                        // running required calculations based on simulation mode
                        switch (ReadFarmSettings.SystemMode)
                        {
                        case "ASTME2848Regression":
                            SimASTM.Calculate(SimMeteoParser);
                            break;

                        case "GridConnected":
                            SimRadProc.Calculate(SimMeteoParser);
                            SimGridSys.Calculate(SimRadProc, SimMeteoParser);
                            LossDiagram.Calculate();
                            break;

                        case "Radiation":
                            SimRadProc.Calculate(SimMeteoParser);
                            break;

                        default:
                            ErrorLogger.Log("Invalid Simulation mode found. CASSYS will exit.", ErrLevel.FATAL);
                            break;
                        }
                        // Only create output string in DLL mode, as creating string causes significant lag
                        if (ReadFarmSettings.outputMode == "str")
                        {
                            OutputString += String.Join(",", GetOutputLine()) + "\n";
                        }
                        // Write to output file
                        else if (ReadFarmSettings.outputMode == "csv")
                        {
                            try
                            {
                                // Assembling and writing the line containing all output values
                                OutputFileWriter.WriteLine(String.Join(",", GetOutputLine()));
                            }
                            catch (IOException ex)
                            {
                                ErrorLogger.Log(ex, ErrLevel.WARNING);
                            }
                        }
                        // Using Iterative Mode: Writes output to a datatable
                        else
                        {
                            // Create row if this is the first simulation run
                            if (ReadFarmSettings.runNumber == 1)
                            {
                                ReadFarmSettings.outputTable.Rows.InsertAt(ReadFarmSettings.outputTable.NewRow(), ReadFarmSettings.outputTable.Rows.Count);
                            }

                            // Write output values to data table
                            ReadFarmSettings.outputTable.Rows[ErrorLogger.iterationCount][ReadFarmSettings.runNumber - 1] = String.Join(",", GetOutputLine());
                        }
                    }

                    if (ReadFarmSettings.outputMode == "str")
                    {
                        // Trim newline character from the end of output
                        OutputString = OutputString.TrimEnd('\r', '\n');
                    }
                    // Write output to .csv file
                    else if (ReadFarmSettings.outputMode == "csv")
                    {
                        try
                        {
                            // Clean out the buffer of the writer to ensure all entries are written to the output file.
                            OutputFileWriter.Flush();
                            OutputFileWriter.Dispose();
                            SimMeteoParser.InputFileReader.Dispose();
                        }
                        catch (IOException ex)
                        {
                            ErrorLogger.Log(ex, ErrLevel.WARNING);
                        }
                    }

                    // If simulation done for Grid connected mode then write the calculated loss values to temp output file
                    if (ReadFarmSettings.SystemMode == "GridConnected")
                    {
                        LossDiagram.AssignLossOutputs();
                    }

                    timeTaken.Stop();

                    Console.WriteLine("");
                    Console.WriteLine("Status: Complete. Simulation took " + timeTaken.ElapsedMilliseconds / 1000D + " seconds.");
                }
                catch (IOException)
                {
                    ErrorLogger.Log("The output file name " + ReadFarmSettings.SimOutputFile + " is not accesible or is not available at the location provided.", ErrLevel.FATAL);
                }
            }
            catch (Exception ex)
            {
                ErrorLogger.Log("CASSYS encountered an unexpected error: " + ex.Message, ErrLevel.FATAL);
            }
        }
Пример #8
0
        double YearsSinceStart;                                 // Number of entire years since the beginning of the simulation

        // Calculate method
        public void Calculate
        (
            RadiationProc RadProc,                              // Radiation related data
            SimMeteo SimMet                                     // Meteological data from inputfile
        )
        {
            // Record number of years since start of simulation
            // This is used to calculate module ageing
            // Update StartTimeStamp if it has never been initialized
            if (StartTimeStamp == new DateTime())
            {
                StartTimeStamp = RadProc.TimeStampAnalyzed;
            }
            TimeSpan SimDelta = RadProc.TimeStampAnalyzed.Subtract(StartTimeStamp);

            YearsSinceStart = Math.Floor(SimDelta.Days / 365.25);

            // Reset Losses
            for (int i = 0; i < SimPVA.Length; i++)
            {
                SimInv[i].LossPMinThreshold = 0;
                SimInv[i].LossClipping      = 0;
                SimInv[i].LossLowVoltage    = 0;
                SimInv[i].LossHighVoltage   = 0;
            }

            // Calculating solar panel shading
            SimShading.Calculate(RadProc.SimSun.Zenith, RadProc.SimSun.Azimuth, RadProc.SimHorizonShading.TDir, RadProc.SimHorizonShading.TDif, RadProc.SimHorizonShading.TRef, RadProc.SimTracker.SurfSlope, RadProc.SimTracker.SurfAzimuth);

            if (RadProc.SimTracker.useBifacial)
            {
                // Calculating shading of ground beneath solar panels
                SimGround.Calculate(RadProc.SimSun.Zenith, RadProc.SimSun.Azimuth, RadProc.SimTracker.SurfSlope, RadProc.SimTracker.SurfAzimuth, RadProc.SimTracker.SurfClearance, RadProc.SimSplitter.HDir,
                                    RadProc.SimSplitter.HDif, RadProc.TimeStampAnalyzed);

                // Get front reflected diffuse irradiance, since it contributes to the back
                SimPVA[0].CalcEffectiveIrradiance(SimShading.ShadTDir, SimShading.ShadTDif, SimShading.ShadTRef, SimBackTilter.BGlo, RadProc.SimTilter.IncidenceAngle, SimMet.MonthOfYear, SimSpectral.clearnessCorrection);

                // Get incidence angle modifiers for components of irradiance
                SimPVA[0].CalcIAM(out SimBackTilter.IAMDir, out SimBackTilter.IAMDif, out SimBackTilter.IAMRef, RadProc.SimTilterOpposite.IncidenceAngle);

                // Calculate back side global irradiance
                SimBackTilter.Calculate(RadProc.SimTracker.SurfSlope, RadProc.SimTracker.SurfClearance, RadProc.SimSplitter.HDif, SimPVA[0].TDifRef, SimMet.HGlo, SimGround.frontGroundGHI, SimGround.rearGroundGHI, SimGround.aveGroundGHI,
                                        SimMet.MonthOfYear, SimShading.BackBeamSF, RadProc.SimTilterOpposite.TDir, RadProc.TimeStampAnalyzed);
            }
            else
            {
                SimBackTilter.BGlo = 0;
            }

            // Calculating spectral model effects
            SimSpectral.Calculate(SimMet.HGlo, RadProc.SimSun.NExtra, RadProc.SimSun.Zenith);

            try
            {
                // Calculate PV Array Output for inputs read in this loop
                for (int j = 0; j < ReadFarmSettings.SubArrayCount; j++)
                {
                    // Adjust the IV Curve based on Temperature and Irradiance.
                    SimPVA[j].CalcIVCurveParameters(SimMet.TGlo, SimShading.ShadTDir, SimShading.ShadTDif, SimShading.ShadTRef, SimBackTilter.BGlo, RadProc.SimTilter.IncidenceAngle, SimMet.TAmbient, SimMet.WindSpeed, SimMet.TModMeasured, SimMet.MonthOfYear, SimSpectral.clearnessCorrection);

                    // Check Inverter status to determine if the Inverter is ON or OFF
                    GetInverterStatus(j);

                    // If inverter is off set appropriate variables to 0 and recalculate array in open circuit voltage
                    if (!SimInv[j].isON)
                    {
                        SimInv[j].ACPwrOut = 0;
                        SimInv[j].IOut     = 0;
                        SimPVA[j].CalcAtOpenCircuit();
                        SimPVA[j].Calculate(false, SimPVA[j].Voc, YearsSinceStart);
                    }

                    //performing AC wiring calculations
                    SimACWiring[j].Calculate(SimInv[j]);

                    // Assigning the outputs to the dictionary
                    ReadFarmSettings.Outputlist["SubArray_Current" + (j + 1).ToString()]     = SimPVA[j].IOut;
                    ReadFarmSettings.Outputlist["SubArray_Voltage" + (j + 1).ToString()]     = SimPVA[j].VOut;
                    ReadFarmSettings.Outputlist["SubArray_Power" + (j + 1).ToString()]       = SimPVA[j].POut / 1000;
                    ReadFarmSettings.Outputlist["SubArray_Current_Inv" + (j + 1).ToString()] = SimInv[j].IOut;
                    ReadFarmSettings.Outputlist["SubArray_Voltage_Inv" + (j + 1).ToString()] = SimInv[j].itsOutputVoltage;
                    ReadFarmSettings.Outputlist["SubArray_Power_Inv" + (j + 1).ToString()]   = SimInv[j].ACPwrOut / 1000;
                }

                // Calculating total farm output and total ohmic loss
                farmACOutput    = 0;
                farmACOhmicLoss = 0;
                for (int i = 0; i < SimInv.Length; i++)
                {
                    farmACOutput    += SimInv[i].ACPwrOut;
                    farmACOhmicLoss += SimACWiring[i].ACWiringLoss;
                }

                SimTransformer.Calculate(farmACOutput - farmACOhmicLoss);

                // Calculating outputs that will be assigned for this interval
                // Shading each component of the Tilted radiaton
                // Using horizon affected tilted radiation
                ShadGloLoss   = (RadProc.SimTilter.TGlo - SimShading.ShadTGlo) - RadProc.SimHorizonShading.LossGlo;
                ShadGloFactor = (RadProc.SimTilter.TGlo > 0 ? SimShading.ShadTGlo / RadProc.SimTilter.TGlo : 1);
                ShadBeamLoss  = RadProc.SimHorizonShading.TDir - SimShading.ShadTDir;
                ShadDiffLoss  = RadProc.SimTilter.TDif > 0 ? RadProc.SimHorizonShading.TDif - SimShading.ShadTDif : 0;
                ShadRefLoss   = RadProc.SimTilter.TRef > 0 ? RadProc.SimHorizonShading.TRef - SimShading.ShadTRef : 0;

                //Calculating total farm level variables. Cleaning them so they are non-cumulative.
                farmDC                  = 0;
                farmDCCurrent           = 0;
                farmDCMismatchLoss      = 0;
                farmDCModuleQualityLoss = 0;
                farmDCModuleLIDLoss     = 0;
                farmDCModuleAgeingLoss  = 0;
                farmDCOhmicLoss         = 0;
                farmDCSoilingLoss       = 0;
                farmDCTemp              = 0;
                farmTotalModules        = 0;
                farmPNomDC              = 0;
                farmPNomAC              = 0;
                farmACPMinThreshLoss    = 0;
                farmACClippingPower     = 0;
                farmACMaxVoltageLoss    = 0;
                farmACMinVoltageLoss    = 0;
                farmPnom                = 0;
                farmTempLoss            = 0;
                farmRadLoss             = 0;

                for (int i = 0; i < SimPVA.Length; i++)
                {
                    farmDC                  += SimPVA[i].POut;
                    farmDCCurrent           += SimPVA[i].IOut;
                    farmDCMismatchLoss      += Math.Max(0, SimPVA[i].MismatchLoss);
                    farmDCModuleQualityLoss += SimPVA[i].ModuleQualityLoss;
                    farmDCModuleLIDLoss     += SimPVA[i].ModuleLIDLoss;
                    farmDCModuleAgeingLoss  += SimPVA[i].ModuleAgeingLoss;
                    farmDCOhmicLoss         += SimPVA[i].OhmicLosses;
                    farmDCSoilingLoss       += SimPVA[i].SoilingLoss;
                    farmDCTemp              += SimPVA[i].TModule * SimPVA[i].itsNumModules;
                    farmTotalModules        += SimPVA[i].itsNumModules;
                    farmPNomDC              += SimPVA[i].itsPNomDCArray;
                    farmPNomAC              += SimInv[i].itsPNomArrayAC;
                    farmACPMinThreshLoss    += SimInv[i].LossPMinThreshold;
                    farmACClippingPower     += SimInv[i].LossClipping;
                    farmACMaxVoltageLoss    += SimInv[i].LossHighVoltage;
                    farmACMinVoltageLoss    += SimInv[i].LossLowVoltage;
                    farmPnom                += (SimPVA[i].itsPNom * SimPVA[i].itsNumModules) * SimPVA[i].RadEff / 1000;
                    farmTempLoss            += SimPVA[i].tempLoss;
                    farmRadLoss             += SimPVA[i].radLoss;
                }

                // Averages all PV Array temperature values
                farmDCTemp /= farmTotalModules;
                farmModuleTempAndAmbientTempDiff = farmDCTemp - SimMet.TAmbient;
                farmDCEfficiency = (RadProc.SimTilter.TGlo > 0 ? farmDC / (RadProc.SimTilter.TGlo * farmArea) : 0) * 100;
                farmPNomDC       = Utilities.ConvertWtokW(farmPNomDC);
                farmPNomAC       = Utilities.ConvertWtokW(farmPNomAC);

                farmOverAllEff = (RadProc.SimTilter.TGlo > 0 && SimTransformer.POut > 0 ? SimTransformer.POut / (RadProc.SimTilter.TGlo * farmArea) : 0) * 100;
                farmPR         = RadProc.SimTilter.TGlo > 0 && farmPNomDC > 0 && SimTransformer.POut > 0 ? SimTransformer.POut / RadProc.SimTilter.TGlo / farmPNomDC : 0;
                farmSysIER     = (SimTransformer.itsPNom - SimTransformer.POut) / (RadProc.SimTilter.TGlo * 1000);
            }
            catch (Exception ce)
            {
                ErrorLogger.Log(ce, ErrLevel.FATAL);
            }

            // Assigning Outputs for this class.
            AssignOutputs();
        }