Beispiel #1
0
        // Config the albedo value based on monthly/yearly values defined on file
        public void ConfigAlbedo()
        {
            // Getting the Albedo values either at a monthly or yearly level
            if (ReadFarmSettings.GetAttribute("Albedo", "Frequency", ErrLevel.WARNING) == "Monthly")
            {
                // Initializing the expected list
                itsMonthlyAlbedo = new double[13];

                // Using the month number as the index, populate the Albedo vales from each correspodning node
                itsMonthlyAlbedo[1]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Jan", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[2]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Feb", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[3]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Mar", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[4]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Apr", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[5]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "May", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[6]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Jun", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[7]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Jul", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[8]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Aug", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[9]  = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Sep", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[10] = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Oct", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[11] = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Nov", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[12] = double.Parse(ReadFarmSettings.GetInnerText("Albedo", "Dec", ErrLevel.WARNING, _default: "0.2"));
            }
            else
            {
                // Initializing the expected list
                itsMonthlyAlbedo    = new double[13];
                itsMonthlyAlbedo[1] = Convert.ToDouble(ReadFarmSettings.GetInnerText("Albedo", "Yearly", ErrLevel.WARNING, _default: "0.2"));

                // Initializing the expected list
                for (int i = 3; i < itsMonthlyAlbedo.Length + 1; i++)
                {
                    itsMonthlyAlbedo[i - 1] = itsMonthlyAlbedo[1];
                }
            }
        }
Beispiel #2
0
        // Config takes values from the xml, which only needs to be done once
        public void Config
        (
        )
        {
            // Loads the spectral model from the .csyx document
            spectralModelUsed = Convert.ToBoolean(ReadFarmSettings.GetInnerText("Spectral", "UseSpectralModel", ErrLevel.WARNING, _default: "false"));
            if (spectralModelUsed == true)
            {
                // Getting the spectral model information from the .csyx file
                SpectralClearnessIndexStr      = ReadFarmSettings.GetInnerText("Spectral", "ClearnessIndex/kt", ErrLevel.WARNING, "0.9", _default: "1");
                SpectralClearnessCorrectionStr = ReadFarmSettings.GetInnerText("Spectral", "ClearnessIndex/ktCorrection", ErrLevel.WARNING, "0.9", _default: "0");

                // Converts the spectral model imported from the .csyx file into an array of doubles
                ClearnessIndexArr      = SpectralCSVStringtoArray(SpectralClearnessIndexStr);
                ClearnessCorrectionArr = SpectralCSVStringtoArray(SpectralClearnessCorrectionStr);

                // If user inputs spectral index/correction data of two different lengths
                if (ClearnessIndexArr.Length != ClearnessCorrectionArr.Length)
                {
                    ErrorLogger.Log("The number of clearness correction values was not equal to the number of clearness index values.", ErrLevel.FATAL);
                }
            }
            else
            {
                ClearnessIndexArr      = new double[] { 1 };
                ClearnessCorrectionArr = new double[] { 0 };
            }
        }
Beispiel #3
0
        // Config takes values from the xml as well as manages calculations that need only to be run once
        public void Config
        (
            double PanelTiltFixed                                // The tilt of the panel, used in config if no tracking is selected [radians]
            , double PanelAzimFixed                              // The azimuth position of the panel, used in config if no tracking is selected [radians]
            , TrackMode ArrayTrackMode                           // The tracking mode, used to determine whether the diffuse fraction can be calculated in config
        )
        {
            // Loads the Horizon Profile from the .csyx document
            horizonDefined = Convert.ToBoolean(ReadFarmSettings.GetInnerText("O&S", "DefineHorizonProfile", ErrLevel.WARNING, _default: "false"));
            if (horizonDefined == true)
            {
                // Getting the horizon information from the .csyx file
                HorizonDefinitionAzimStr = ReadFarmSettings.GetInnerText("O&S", "HorizonAzi", ErrLevel.WARNING, "0.9", _default: "0");
                HorizonDefinitionElevStr = ReadFarmSettings.GetInnerText("O&S", "HorizonElev", ErrLevel.WARNING, "0.9", _default: "0");

                // Converts the Horizon Profile imported from the.csyx document into an array of doubles
                HorizonAzim = HorizonCSVStringtoArray(HorizonDefinitionAzimStr);
                HorizonElev = HorizonCSVStringtoArray(HorizonDefinitionElevStr);

                // If user inputs horizon azimuth/elevation data of two different lengths
                if (HorizonAzim.Length != HorizonElev.Length)
                {
                    ErrorLogger.Log("The number of horizon azimuth values is not equal to the number of horizon elevation values.", ErrLevel.FATAL);
                }

                // Extends the Horizon Profile by duplicating the first and last values and transposing them 360 degrees forward and backwards, respectively
                CalcExtendedHorizon(HorizonAzim, HorizonElev, out HorizonAzimExtended, out HorizonElevExtended);

                // The full azimuthal range of the Horizon Profile is filled in using Interpolation
                // The horizon profile must be calculated here both for the non-tracking case, as well as for the ground reflected diffuse factor for all tracking cases
                // It is calculated separately in the Calculate method for tracking cases
                HorizonAzimInterpolated = InitializeHorizonProfile(PanelAzimFixed);

                HorizonElevInterpolated = GetInterpolatedElevationProfile(HorizonAzimExtended, HorizonElevExtended, HorizonAzimInterpolated);

                // If there is no tracking implemented the diffuse horizon factor only needs to be calculated once, it is otherwise calculated in the Calculate method
                if (ArrayTrackMode == TrackMode.NOAT && ReadFarmSettings.UsePOA != true)
                {
                    // Calculates the limiting angle array
                    LimitingAngle = GetLimitingAngleArray(PanelTiltFixed, PanelAzimFixed, HorizonAzimInterpolated);

                    // The shading factor is calculated via numerical computation using the mathematical models described in the CASSYS documentation
                    DiffFactor = GetHorizonDiffuseFactor(PanelTiltFixed, PanelAzimFixed, HorizonAzimInterpolated, HorizonElevInterpolated, LimitingAngle);
                }

                // Creating the limiting angle array for the ground, all values are PI/2
                RefLimitingAngle = new double[361];
                for (int i = 0; i < RefLimitingAngle.Length; i++)
                {
                    RefLimitingAngle[i] = Math.PI / 2;
                }

                // Diffuse part of ground reflected factor only needs to be calculated once. 0s are used for azimuth and tilt of surface, as it represents the ground.
                RefDiffFactor = GetHorizonDiffuseFactor(0, 0, HorizonAzimInterpolated, HorizonElevInterpolated, RefLimitingAngle);
            }
        }
Beispiel #4
0
 // Config will assign parameter variables their values as obtained from the .CSYX file
 public void Config
 (
     int ArrayNum
     , double OperatingVoltage
     , double Phases
     , double MaximumInputPower
 )
 {
     itsACWiringLossPC = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "LossFraction", _ArrayNum: ArrayNum));
     itsACWiringRes    = itsACWiringLossPC * OperatingVoltage / (MaximumInputPower / (OperatingVoltage * Math.Sqrt(Phases)));
 }
Beispiel #5
0
        // Config will assign parameter variables their values as obtained from the .CSYX file
        public void Config()
        {
            // Gathering the parameters for the Sun Class
            //itsSurfaceSlope = Util.DTOR * double.Parse(ReadFarmSettings.GetInnerText("O&S", "PlaneTilt")); TODO: Re-evaluate.
            itsSLat    = double.Parse(ReadFarmSettings.GetInnerText("Site", "Latitude"));
            itsSLong   = double.Parse(ReadFarmSettings.GetInnerText("Site", "Longitude"));
            itsLSTFlag = Convert.ToBoolean(ReadFarmSettings.GetInnerText("Site", "UseLocTime"));

            // If Local Standard Time is to be used, get the reference meridian for the "Standard Time" of the region
            if (itsLSTFlag)
            {
                itsMLong = double.Parse(ReadFarmSettings.GetInnerText("Site", "RefMer"));
            }
        }
Beispiel #6
0
        // Calculation method
        public void Calculate
        (
            double NDir              // normal direct irradiance [W/m2]
            , double HDif            // horizontal diffuse irradiance [W/m2]
            , double NExtra          // normal extraterrestrial irradiance [W/m2]
            , double SunZenith       // zenith angle of sun [radians]
            , double SunAzimuth      // azimuth angle of sun [radians]
            , double AirMass         // air mass [#]
            , int MonthNum           // The month number of the time stamp [1->12]
            , double MeasAlbedo      // albedo read from climate file, if available (NaN otherwise)
        )
        {
            // Calculate albedo
            // Read from climate file
            if (ReadFarmSettings.GetAttribute("Albedo", "Frequency", ErrLevel.WARNING) == "From Climate File")
            {
                Albedo = MeasAlbedo;
            }
            // Otherwise, read from monthly array
            else
            {
                Albedo = itsMonthlyAlbedo[MonthNum];
            }

            // Calculate direct horizontal if direct normal is provided
            double HDir = NDir * Math.Cos(SunZenith);

            // call Perez et al. algorithm or Hay algorithm
            switch (itsTiltAlgorithm)
            {
            case TiltAlgorithm.PEREZ:
                TGlo = GetTiltCompIrradPerez(out TDir, out TDif, out TRef, HDir, HDif, NExtra, SunZenith, SunAzimuth, AirMass, MonthNum);
                break;

            case TiltAlgorithm.HAY:
                TGlo = GetTiltCompIrradHay(out TDir, out TDif, out TRef, HDir, HDif, NExtra, SunZenith, SunAzimuth, MonthNum);
                break;

            default:
                itsTiltAlgorithm = TiltAlgorithm.HAY;
                break;
            }

            // Compute the incidence angle from the Tilt class
            IncidenceAngle = Tilt.GetIncidenceAngle(SunZenith, SunAzimuth, itsSurfaceSlope, itsSurfaceAzimuth);
        }
Beispiel #7
0
        // Config will assign parameter variables their values as obtained from the .CSYX file
        public void ConfigPyranometer()
        {
            try
            {
                // Getting the parameter values
                itsSurfaceSlope       = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("InputFile", "MeterTilt", ErrLevel.WARNING, _default: "N/A"));
                itsSurfaceAzimuth     = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("InputFile", "MeterAzimuth", ErrLevel.WARNING, _default: "N/A"));
                NoPyranoAnglesDefined = false;
            }
            catch
            {
                ErrorLogger.Log("Irradiance Meter Tilt or Azimuth were not specified. CASSYS will assume these values are the same as the Array Tilt and Azimuth. This can be changed in the Climate File Sheet in the interface.", ErrLevel.WARNING);
                NoPyranoAnglesDefined = true;
            }

            // Assign the albedo parameters from the .CSYX file
            ConfigAlbedo();
        }
Beispiel #8
0
        // Config the albedo value based on monthly/yearly values defined on file
        void ConfigAlbedo()
        {
            // Determine whether to use site albedo values, or inter-row specific albedo values
            string whichAlbedo;

            if (Convert.ToBoolean(ReadFarmSettings.GetInnerText("BifAlbedo", "UseBifAlb", ErrLevel.FATAL)))
            {
                whichAlbedo = "BifAlbedo";
            }
            else
            {
                whichAlbedo = "Albedo";
            }

            // Initializing the expected list
            itsMonthlyAlbedo = new double[13];
            if (ReadFarmSettings.GetAttribute(whichAlbedo, "Frequency", ErrLevel.WARNING) == "Monthly")
            {
                // Using the month number as the index, populate the albedo vales from each corresponding node
                itsMonthlyAlbedo[1]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Jan", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[2]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Feb", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[3]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Mar", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[4]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Apr", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[5]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "May", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[6]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Jun", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[7]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Jul", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[8]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Aug", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[9]  = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Sep", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[10] = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Oct", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[11] = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Nov", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[12] = double.Parse(ReadFarmSettings.GetInnerText(whichAlbedo, "Dec", ErrLevel.WARNING, _default: "0.2"));
            }
            else if (ReadFarmSettings.GetAttribute(whichAlbedo, "Frequency", ErrLevel.WARNING) == "Yearly")
            {
                itsMonthlyAlbedo[1] = Convert.ToDouble(ReadFarmSettings.GetInnerText(whichAlbedo, "Yearly", ErrLevel.WARNING, _default: "0.2"));

                // Apply the same albedo to all months
                for (int i = 3; i < itsMonthlyAlbedo.Length + 1; i++)
                {
                    itsMonthlyAlbedo[i - 1] = itsMonthlyAlbedo[1];
                }
            }
        }
Beispiel #9
0
        // Config will assign parameter variables their values as obtained from the XML file
        public void Config()
        {
            // Getting the Tilt Algorithm for the Simulation
            if (ReadFarmSettings.GetInnerText("SiteDef", "TransEnum", ErrLevel.WARNING) == "0")
            {
                itsTiltAlgorithm = TiltAlgorithm.HAY;
            }
            else if (ReadFarmSettings.GetInnerText("SiteDef", "TransEnum", ErrLevel.WARNING) == "1")
            {
                itsTiltAlgorithm = TiltAlgorithm.PEREZ;
            }
            else
            {
                ErrorLogger.Log("Tilter: Invalid tilt algorithm chosen by User. CASSYS uses Hay as default.", ErrLevel.WARNING);
                itsTiltAlgorithm = TiltAlgorithm.HAY;
            }

            // Assign the albedo parameters from the .CSYX file
            ConfigAlbedo();
        }
Beispiel #10
0
        // Config the albedo value based on monthly/yearly values defined on file
        void ConfigAlbedo()
        {
            // Initializing the expected list
            itsMonthlyAlbedo = new double[13];
            if (ReadFarmSettings.GetAttribute("BifAlbedo", "Frequency", ErrLevel.WARNING) == "Monthly")
            {
                // Using the month number as the index, populate the albedo vales from each corresponding node
                itsMonthlyAlbedo[1]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Jan", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[2]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Feb", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[3]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Mar", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[4]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Apr", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[5]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "May", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[6]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Jun", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[7]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Jul", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[8]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Aug", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[9]  = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Sep", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[10] = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Oct", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[11] = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Nov", ErrLevel.WARNING, _default: "0.2"));
                itsMonthlyAlbedo[12] = double.Parse(ReadFarmSettings.GetInnerText("BifAlbedo", "Dec", ErrLevel.WARNING, _default: "0.2"));
            }
            else if (ReadFarmSettings.GetAttribute("BifAlbedo", "Frequency", ErrLevel.WARNING) == "Yearly")
            {
                itsMonthlyAlbedo[1] = Convert.ToDouble(ReadFarmSettings.GetInnerText("BifAlbedo", "Yearly", ErrLevel.WARNING, _default: "0.2"));

                // Apply the same albedo to all months
                for (int i = 2; i < 13; i++)
                {
                    itsMonthlyAlbedo[i] = itsMonthlyAlbedo[1];
                }
            }
            else                    // read from file or equal to site albedo - set monthly valus to NaN for safety
            {
                for (int i = 1; i < 13; i++)
                {
                    itsMonthlyAlbedo[i] = Double.NaN;
                }
            }
        }
Beispiel #11
0
        // Config will assign parameter variables their values as obtained from the .CSYX file
        public void Config()
        {
            try
            {
                // Gathering all the parameters from ASTM E2848 Element
                itsPmax = double.Parse(ReadFarmSettings.GetInnerText("ASTM", "SystemPmax", _Error: ErrLevel.FATAL));
                itsA1   = double.Parse(ReadFarmSettings.GetInnerText("ASTM/Coeffs", "ASTM1", _Error: ErrLevel.FATAL));
                itsA2   = double.Parse(ReadFarmSettings.GetInnerText("ASTM/Coeffs", "ASTM2", _Error: ErrLevel.FATAL));
                itsA3   = double.Parse(ReadFarmSettings.GetInnerText("ASTM/Coeffs", "ASTM3", _Error: ErrLevel.FATAL));
                itsA4   = double.Parse(ReadFarmSettings.GetInnerText("ASTM/Coeffs", "ASTM4", _Error: ErrLevel.FATAL));

                // Looping through and assigning all EAF parameters from EAF Element
                string[] months = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
                for (int i = 0; i < 12; i++)
                {
                    itsEAF[i] = double.Parse(ReadFarmSettings.GetInnerText("ASTM/EAF", months[i], _Error: ErrLevel.FATAL));
                }
            }
            catch (Exception e)
            {
                ErrorLogger.Log("ASTM E2848 Config: " + e.Message, ErrLevel.FATAL);
            }
        }
Beispiel #12
0
        //Config will determine and assign values for the losses at the transformer using an .CSYX file
        public void Config()
        {
            //call variables from ReadFarmSettings to determine version of CASSYS
            new ReadFarmSettings();
            string version = ReadFarmSettings.doc.SelectSingleNode("/Site/Version").InnerXml;

            // Config will find the Iron Losses, and Global losses from the file. The resistive loss, etc are calculated by the program from these two values.
            itsPIronLoss = Convert.ToDouble(ReadFarmSettings.GetInnerText("Transformer", "PIronLossTrf", ErrLevel.WARNING)) * 1000;

            itsPNom    = Convert.ToDouble(ReadFarmSettings.GetInnerText("Transformer", "PNomTrf", ErrLevel.WARNING)) * 1000;
            itsPResLss = Convert.ToDouble(ReadFarmSettings.GetInnerText("Transformer", "PResLssTrf", ErrLevel.WARNING)) * 1000;

            if (string.CompareOrdinal("1.2.0", version) > 0)
            {
                itsPGlobLoss = Convert.ToDouble(ReadFarmSettings.GetInnerText("Transformer", "PGlobLossTrf", ErrLevel.WARNING)) * 1000;
            }
            else
            {
                itsPGlobLoss = Convert.ToDouble(ReadFarmSettings.GetInnerText("Transformer", "PFullLoadLss", ErrLevel.WARNING)) * 1000;
            }

            // Parameters that determine if the transformer remains ON at night, and initializing the disconnection of the transformer.
            isNightlyDisconnected = Convert.ToBoolean(ReadFarmSettings.GetInnerText("Transformer", "NightlyDisconnect", ErrLevel.WARNING, _default: "False"));
        }
Beispiel #13
0
        // Finding and assigning the number of CellRows
        public static void AssignCellRowsNum()
        {
            if (string.Compare(SystemMode, "GridConnected") == 0)
            {
                // Getting the number of back cell rows for this file
                if (Convert.ToBoolean(ReadFarmSettings.GetInnerText("Bifacial", "UseBifacialModel", ErrLevel.FATAL)))
                {
                    switch (ReadFarmSettings.GetAttribute("O&S", "ArrayType", ErrLevel.FATAL))
                    {
                    case "Fixed Tilted Plane":
                        numCellRows = Util.NUM_CELLS_PANEL * int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWid", ErrLevel.WARNING, _default: "1"));
                        break;

                    case "Unlimited Rows":
                        numCellRows = Util.NUM_CELLS_PANEL * int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWid", ErrLevel.WARNING, _default: "1"));
                        break;

                    case "Single Axis Elevation Tracking (E-W)":
                        numCellRows = Util.NUM_CELLS_PANEL * int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWidSAET", ErrLevel.WARNING, _default: "1"));
                        break;

                    case "Single Axis Horizontal Tracking (N-S)":
                        numCellRows = Util.NUM_CELLS_PANEL * int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWidSAST", ErrLevel.WARNING, _default: "1"));
                        break;

                    default:
                        ErrorLogger.Log("Bifacial is not supported for the selected orientation and shading.", ErrLevel.FATAL);
                        break;
                    }
                }
                else
                {
                    numCellRows = Util.NUM_CELLS_PANEL;
                }
            }
        }
Beispiel #14
0
        public static void Main(string[] args)
        {
            // Showing the Header of the Simulation Program in the Console
            if (ReadFarmSettings.outputMode != "str")
            {
                ReadFarmSettings.ShowHeader();
            }

            // Declaring a new simulation object
            PVPlant      = new Simulation();
            SiteSettings = new XmlDocument();

            // Load CSYX file
            try
            {
                if (args.Length == 0)
                {
                    // Set batch mode to true, and Ask user for all the arguments
                    Console.WriteLine("Status: You are running CASSYS in batch mode.");
                    Console.WriteLine("Status: You will need to provide a CASSYS Site File (.CSYX), Input File, and Output File Path.");
                    Console.WriteLine("Enter CASSYS Site (.CSYX) File Path: ");
                    String SimFilePath = Console.ReadLine();
                    Console.WriteLine("Enter Input file path (.csv file): ");
                    SimInputFilePath = Console.ReadLine();
                    Console.WriteLine("Enter an Output file path (.csv file, Note: if the file exists this will append your results to the file): ");
                    SimOutputFilePath = Console.ReadLine();

                    SiteSettings.Load(SimFilePath.Replace("\\", "/"));
                    ErrorLogger.RunFileName = SimFilePath;
                    ErrorLogger.Clean();
                }
                else
                {
                    // Get .CSYX file name from CMDPrompt, and Load document
                    SiteSettings.Load(args[0]);
                    ErrorLogger.RunFileName = args[0];
                }

                // Assigning Xml document to ReadFarmSettings to allow reading of XML document. Check CSYX version
                ReadFarmSettings.doc = SiteSettings;
                ReadFarmSettings.CheckCSYXVersion();

                // Variable Parameter mode
                if (ReadFarmSettings.doc.SelectSingleNode("/Site/Iterations/Iteration1") != null)
                {
                    variableParameters(args);
                }
                else if (args.Length == 1)
                {
                    // Running the Simulation based on the CASSYS Configuration File provided
                    ReadFarmSettings.batchMode = false;
                    PVPlant.Simulate(SiteSettings);
                    // Show the end of simulation message, window should be kept open for longer
                    ReadFarmSettings.ShowFooter();
                }
                else if (args.Length == 3)
                {
                    // Set batch mode to true, and Run from command prompt arguments directly
                    ReadFarmSettings.batchMode = true;
                    PVPlant.Simulate(SiteSettings, _Input: args[1], _Output: args[2]);
                }
                else if (args.Length == 0)
                {
                    PVPlant.Simulate(SiteSettings, _Input: SimInputFilePath.Replace("\\", "/"), _Output: SimOutputFilePath.Replace("\\", "/"));
                }
                else
                {
                    // CASSYS needs a site file name to run, so warn the user and exit the program.
                    ErrorLogger.Log("No site file provided for CASSYS to simulate. Please select a valid .CSYX file.", ErrLevel.FATAL);
                }
            }
            catch (Exception)
            {
                ErrorLogger.Log("CASSYS was unable to access or load the Site XML file. Simulation has ended.", ErrLevel.FATAL);
            }
        }
Beispiel #15
0
        static void variableParameters(string[] args)
        {
            ReadFarmSettings.outputMode = "var";
            ReadFarmSettings.batchMode  = true;

            // Assign input and output file path for simulation run.
            // File paths have already been assigned in case of no input arguments
            if (args.Length == 1)
            {
                SimInputFilePath  = null;
                SimOutputFilePath = null;
            }
            else if (args.Length == 3)
            {
                SimInputFilePath  = args[1];
                SimOutputFilePath = args[2];
            }

            // Gathering information on parameter to be changed
            paramPath = ReadFarmSettings.GetAttribute("Iteration1", "ParamPath", _Error: ErrLevel.FATAL);
            start     = double.Parse(ReadFarmSettings.GetAttribute("Iteration1", "Start", _Error: ErrLevel.FATAL));
            end       = double.Parse(ReadFarmSettings.GetAttribute("Iteration1", "End", _Error: ErrLevel.FATAL));
            interval  = double.Parse(ReadFarmSettings.GetAttribute("Iteration1", "Interval", _Error: ErrLevel.FATAL));

            // Number of simulations ran
            ReadFarmSettings.runNumber = 1;

            // Data table to hold output for various runs
            ReadFarmSettings.outputTable = new DataTable();

            // Row used to hold parameter information
            ReadFarmSettings.outputTable.Rows.InsertAt(ReadFarmSettings.outputTable.NewRow(), 0);

            // Loop through values of variable parameter
            for (double value = start; value <= end; value = value + interval)
            {
                // iterationCount used to determine current row in data base
                ErrorLogger.iterationCount = 0;
                // Reset outputheader between runs
                ReadFarmSettings.OutputHeader = null;

                // Vary parameter in XML object
                SiteSettings.SelectSingleNode(paramPath).InnerText = Convert.ToString(value);

                // Creating column to store data from run
                // A single column stores the all data from the simulation run
                ReadFarmSettings.outputTable.Columns.Add(paramPath + "=" + value, typeof(String));

                PVPlant.Simulate(SiteSettings, SimInputFilePath, SimOutputFilePath);
                ReadFarmSettings.runNumber++;
            }

            try
            {
                // Write data table output to csv file
                OutputFileWriter = new StreamWriter(ReadFarmSettings.SimOutputFile);
                WriteDataTable(ReadFarmSettings.outputTable, OutputFileWriter);
                OutputFileWriter.Dispose();
            }
            catch (IOException ex)
            {
                ErrorLogger.Log("Error occured while creating to output file. Error: " + ex, ErrLevel.FATAL);
            }
        }
Beispiel #16
0
        // Config manages calculations and initializations that need only to be run once
        public void Config()
        {
            useBifacial = Convert.ToBoolean(ReadFarmSettings.GetInnerText("Bifacial", "UseBifacialModel", ErrLevel.FATAL));

            if (useBifacial)
            {
                switch (ReadFarmSettings.GetAttribute("O&S", "ArrayType", ErrLevel.FATAL))
                {
                // In all cases, pitch must be normalized to panel slope lengths
                case "Fixed Tilted Plane":
                    if (String.Compare(ReadFarmSettings.CASSYSCSYXVersion, "0.9.3") >= 0)
                    {
                        itsPanelTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTiltFix", ErrLevel.FATAL));
                    }
                    else
                    {
                        itsPanelTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTilt", ErrLevel.FATAL));
                    }
                    // itsPitch will be assigned in the below (numRows == 1) conditional
                    itsArrayBW   = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "CollBandWidthFix", ErrLevel.FATAL));
                    itsClearance = Convert.ToDouble(ReadFarmSettings.GetInnerText("Bifacial", "GroundClearance", ErrLevel.FATAL)) / itsArrayBW;

                    // Find number of cell rows on back of array [#]
                    numCellRows = Util.NUM_CELLS_PANEL * int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWid", ErrLevel.WARNING, _default: "1"));
                    numRows     = 1;
                    break;

                case "Unlimited Rows":
                    itsPanelTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTilt", ErrLevel.FATAL));
                    itsArrayBW   = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "CollBandWidth", ErrLevel.FATAL));
                    itsPitch     = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "Pitch", ErrLevel.FATAL)) / itsArrayBW;
                    itsClearance = Convert.ToDouble(ReadFarmSettings.GetInnerText("Bifacial", "GroundClearance", ErrLevel.FATAL)) / itsArrayBW;

                    // Find number of cell rows on back of array [#]
                    numCellRows = Util.NUM_CELLS_PANEL * int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWid", ErrLevel.WARNING, _default: "1"));
                    numRows     = int.Parse(ReadFarmSettings.GetInnerText("O&S", "RowsBlock", ErrLevel.FATAL));
                    break;

                case "Single Axis Elevation Tracking (E-W)":
                    itsArrayBW = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "WActiveSAET", ErrLevel.FATAL));
                    itsPitch   = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PitchSAET", ErrLevel.FATAL)) / itsArrayBW;

                    // Find number of cell rows on back of array [#]
                    numCellRows = Util.NUM_CELLS_PANEL * int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWidSAET", ErrLevel.WARNING, _default: "1"));
                    numRows     = int.Parse(ReadFarmSettings.GetInnerText("O&S", "RowsBlockSAET", ErrLevel.FATAL));
                    break;

                case "Single Axis Horizontal Tracking (N-S)":
                    itsArrayBW = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "WActiveSAST", ErrLevel.FATAL));
                    itsPitch   = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PitchSAST", ErrLevel.FATAL)) / itsArrayBW;

                    // Find number of cell rows on back of array [#]
                    numCellRows = Util.NUM_CELLS_PANEL * int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWidSAST", ErrLevel.WARNING, _default: "1"));
                    numRows     = int.Parse(ReadFarmSettings.GetInnerText("O&S", "RowsBlockSAST", ErrLevel.FATAL));
                    break;

                default:
                    ErrorLogger.Log("Bifacial is not supported for the selected orientation and shading.", ErrLevel.FATAL);
                    break;
                }

                structLossFactor = Convert.ToDouble(ReadFarmSettings.GetInnerText("Bifacial", "StructBlockingFactor", ErrLevel.FATAL));

                if (numRows == 1)
                {
                    // Pitch is needed for a single row because of ground patch calculations and geometry. Take value 100x greater than array bandwidth.
                    itsPitch   = 100;
                    itsRowType = RowType.SINGLE;
                }
                else
                {
                    itsRowType = RowType.INTERIOR;
                }

                // Initialize arrays
                backGlo    = new double[numCellRows];
                backDir    = new double[numCellRows];
                backDif    = new double[numCellRows];
                backFroRef = new double[numCellRows];
                backGroRef = new double[numCellRows];

                ConfigAlbedo();
            }
            else
            {
                // Allows back irradiance profile output even when bifacial is disabled
                numCellRows = Util.NUM_CELLS_PANEL;
                backGlo     = new double[numCellRows];
            }
        }
Beispiel #17
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);
            }
        }
Beispiel #18
0
        // Config will assign parameter variables their values as obtained from the .CSYX file
        public void Config(int ArrayNum)
        {
            itsNomOutputPwr  = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "PNomAC", _ArrayNum: ArrayNum)) * 1000;
            itsMinVoltage    = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Min.V", _ArrayNum: ArrayNum));
            itsMaxVoltage    = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Max.V", _ArrayNum: ArrayNum, _default: itsMppWindowMax.ToString()));
            itsNumInverters  = int.Parse(ReadFarmSettings.GetInnerText("Inverter", "NumInverters", _ArrayNum: ArrayNum));
            itsOutputVoltage = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Output", _ArrayNum: ArrayNum));
            itsPNomArrayAC   = itsNomOutputPwr * itsNumInverters;
            itsThresholdPwr  = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Threshold", _ArrayNum: ArrayNum));

            // Assigning the number of output phases;
            if (ReadFarmSettings.GetInnerText("Inverter", "Type", _ArrayNum: ArrayNum) == "Tri")
            {
                // Tri-phase Inverter
                outputPhases = 3;
            }
            else if (ReadFarmSettings.GetInnerText("Inverter", "Type", _ArrayNum: ArrayNum) == "Bi")
            {
                // Bi-phase inverter
                outputPhases = 2;
            }
            else if (ReadFarmSettings.GetInnerText("Inverter", "Type", _ArrayNum: ArrayNum) == "Mono")
            {
                outputPhases = 1;
            }
            else
            {
                ErrorLogger.Log("The Inverter output phase definition was not found. Please check the Inverter in the Inverter database.", ErrLevel.FATAL);
            }

            // Assigning the operation type of the Inverter
            if (ReadFarmSettings.GetInnerText("Inverter", "Oper.", _ArrayNum: ArrayNum) == "MPPT")
            {
                itsMPPTracking  = true;
                itsMppWindowMin = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "MinMPP", _ArrayNum: ArrayNum));
                itsMppWindowMax = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "MaxMPP", _ArrayNum: ArrayNum));
            }
            else
            {
                ErrorLogger.Log("The Inverter does not operate in MPPT according to the configurations. CASSYS does not support these inverters at this time. Simulation has ended.", ErrLevel.FATAL);
                itsMPPTracking = false;
            }

            // Assigning if the Inverter is Bipolar or not
            if ((ReadFarmSettings.GetInnerText("Inverter", "BipolarInput", _ArrayNum: ArrayNum, _Error: ErrLevel.WARNING, _default: "false") == "Yes") || (ReadFarmSettings.GetInnerText("Inverter", "BipolarInput", _ArrayNum: ArrayNum, _Error: ErrLevel.WARNING, _default: "false") == "True") || (ReadFarmSettings.GetInnerText("Inverter", "BipolarInput", _ArrayNum: ArrayNum, _Error: ErrLevel.WARNING, _default: "false") == "Bipolar inputs"))
            {
                isBipolar = true;
                // itsThresholdPwr = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Threshold", _ArrayNum: ArrayNum));
            }
            else
            {
                isBipolar = false;
                // itsThresholdPwr = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Threshold", _ArrayNum: ArrayNum));
            }

            // Inverter Efficiency Curve Configuration
            threeCurves = Convert.ToBoolean(ReadFarmSettings.GetInnerText("Inverter", "MultiCurve", _ArrayNum: ArrayNum));

            // Initialization of efficiency curve arrays
            itsMedEff[0]  = new double[8];
            itsMedEff[1]  = new double[8];
            itsHighEff[0] = new double[8];
            itsHighEff[1] = new double[8];

            // Initialization of efficiency curve arrays
            itsOnlyEff[0] = new double[8];
            itsOnlyEff[1] = new double[8];

            // Configuration of the Efficiency Curves for the Inverter
            ConfigEffCurves(ArrayNum, threeCurves);

            if (string.Compare(ReadFarmSettings.CASSYSCSYXVersion, "1.2.0") >= 0 && Convert.ToBoolean(ReadFarmSettings.GetInnerText("System", "ACWiringLossAtSTC", _Error: ErrLevel.FATAL)))
            {
                itsMaxSubArrayACEff = 1;
            }
            else if (threeCurves)
            {
                itsMaxSubArrayACEff = itsMedEff[1][itsMedEff[1].Length - 1] / itsMedEff[0][itsMedEff[0].Length - 1];
            }
            else
            {
                itsMaxSubArrayACEff = itsOnlyEff[1][itsOnlyEff[1].Length - 1] / itsOnlyEff[0][itsOnlyEff[0].Length - 1];
            }
        }
Beispiel #19
0
        public void Config()
        {
            // Determine the type of Array layout
            switch (ReadFarmSettings.GetAttribute("O&S", "ArrayType", ErrLevel.FATAL))
            {
            case "Unlimited Rows":
                itsShadModel = ShadModel.UR;
                break;

            case "Fixed Tilted Plane":
                itsShadModel = ShadModel.FT;
                break;

            case "Fixed Tilted Plane Seasonal Adjustment":
                itsShadModel = ShadModel.FT;
                break;

            case "Single Axis Elevation Tracking (E-W)":
                itsShadModel = ShadModel.TE;
                break;

            case "Single Axis Horizontal Tracking (N-S)":
                itsShadModel = ShadModel.TS;
                break;

            default:
                itsShadModel = ShadModel.None;
                break;
            }

            // reading and assigning values to the parameters for the Shading class based on the Array layout
            switch (itsShadModel)
            {
            case ShadModel.UR:

                // Defining all the parameters for the shading of a unlimited row array configuration
                itsCollTilt    = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTilt", ErrLevel.FATAL));
                itsCollAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "Azimuth", ErrLevel.FATAL));
                itsPitch       = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "Pitch", ErrLevel.FATAL));
                itsCollBW      = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "CollBandWidth", ErrLevel.FATAL));

                itsRowsBlock      = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "RowsBlock", ErrLevel.FATAL));
                itsRowBlockFactor = (itsRowsBlock - 1) / itsRowsBlock;

                // Collecting definitions for cell based shading models or preparing for its absence
                useCellBasedShading = Convert.ToBoolean(ReadFarmSettings.GetInnerText("O&S", "UseCellVal", ErrLevel.WARNING, _default: "false"));

                // Set up the arrays to allow for shading calculations according to electrical effect
                if (useCellBasedShading)
                {
                    CellSize = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "CellSize", ErrLevel.FATAL)) / 100D;
                    itsNumModTransverseStrings = int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWid", ErrLevel.FATAL));
                    itsRowBlockFactor          = 1; // No row related shading adjustments should be applied.

                    // Use cell based shading to calculate the effect on the beam shading factor
                    // The shading factor gets worse in steps based on how much of the collector bandwidth is currently under shadowed length
                    cellSetup = new double[itsNumModTransverseStrings + 1];
                    shadingPC = new double[itsNumModTransverseStrings + 1];

                    // Defining the arrays needed for Number of cells in each string (transverse) and shading %
                    for (int i = 1; i <= itsNumModTransverseStrings; i++)
                    {
                        cellSetup[i] = (double)i / (double)itsNumModTransverseStrings * (itsCollBW / CellSize);
                        shadingPC[i] = (double)i / (double)itsNumModTransverseStrings;
                    }
                }
                break;

            case ShadModel.TE:
                itsPitch     = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PitchSAET", ErrLevel.FATAL));
                itsCollBW    = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "WActiveSAET", ErrLevel.FATAL));
                itsRowsBlock = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "RowsBlockSAET", ErrLevel.FATAL));


                itsRowBlockFactor = (itsRowsBlock - 1) / itsRowsBlock;



                // NB: Using same formula as Unlimited Rows, with SAET added to variable names
                // Collecting definitions for cell based shading models or preparing for its absence
                useCellBasedShading = Convert.ToBoolean(ReadFarmSettings.GetInnerText("O&S", "UseCellValSAET", ErrLevel.WARNING, _default: "false"));

                // Set up the arrays to allow for shading calculations according to electrical effect
                if (useCellBasedShading)
                {
                    CellSize = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "CellSizeSAET", ErrLevel.FATAL)) / 100D;
                    itsNumModTransverseStrings = int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWidSAET", ErrLevel.FATAL));
                    itsRowBlockFactor          = 1; // No row related shading adjustments should be applied.

                    // Use cell based shading to calculate the effect on the beam shading factor
                    // The shading factor gets worse in steps based on how much of the collector bandwidth is currently under shadowed length
                    cellSetup = new double[itsNumModTransverseStrings + 1];
                    shadingPC = new double[itsNumModTransverseStrings + 1];

                    // Defining the arrays needed for Number of cells in each string (transverse) and shading %
                    for (int i = 1; i <= itsNumModTransverseStrings; i++)
                    {
                        cellSetup[i] = (double)i / (double)itsNumModTransverseStrings * (itsCollBW / CellSize);
                        shadingPC[i] = (double)i / (double)itsNumModTransverseStrings;
                    }
                }

                break;

            case ShadModel.TS:
                itsPitch     = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PitchSAST", ErrLevel.FATAL));
                itsCollBW    = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "WActiveSAST", ErrLevel.FATAL));
                itsRowsBlock = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "RowsBlockSAST", ErrLevel.FATAL));

                itsRowBlockFactor = (itsRowsBlock - 1) / itsRowsBlock;


                // NB: Using same formula as Unlimited Rows, with SAST added to variable names
                // Collecting definitions for cell based shading models or preparing for its absence
                useCellBasedShading = Convert.ToBoolean(ReadFarmSettings.GetInnerText("O&S", "UseCellValSAST", ErrLevel.WARNING, _default: "false"));

                // Set up the arrays to allow for shading calculations according to electrical effect
                if (useCellBasedShading)
                {
                    CellSize = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "CellSizeSAST", ErrLevel.FATAL)) / 100D;
                    itsNumModTransverseStrings = int.Parse(ReadFarmSettings.GetInnerText("O&S", "StrInWidSAST", ErrLevel.FATAL));
                    itsRowBlockFactor          = 1; // No row related shading adjustments should be applied.

                    // Use cell based shading to calculate the effect on the beam shading factor
                    // The shading factor gets worse in steps based on how much of the collector bandwidth is currently under shadowed length
                    cellSetup = new double[itsNumModTransverseStrings + 1];
                    shadingPC = new double[itsNumModTransverseStrings + 1];

                    // Defining the arrays needed for Number of cells in each string (transverse) and shading %
                    for (int i = 1; i <= itsNumModTransverseStrings; i++)
                    {
                        cellSetup[i] = (double)i / (double)itsNumModTransverseStrings * (itsCollBW / CellSize);
                        shadingPC[i] = (double)i / (double)itsNumModTransverseStrings;
                    }
                }

                break;

            case ShadModel.FT:

                // Defining the parameters for the shading for a fixed tilt configuration
                FrontSLA = 0;
                BackSLA  = 0;

                // Running one-time only methods - the shading factors applied to diffuse and ground reflected component are constant and 1.
                DiffuseSF   = 1;
                ReflectedSF = 1;
                break;

            case ShadModel.None:
                // No shading applies.
                DiffuseSF   = 1;
                ReflectedSF = 1;
                BeamSF      = 1;
                break;
            }
        }
Beispiel #20
0
        // Configuring the required elements for a grid connected system
        public void Config()
        {
            SimShading.Config();
            SimTransformer.Config();
            SimSpectral.Config();

            // Array of PVArray, Inverter and Wiring objects based on the number of Sub-Arrays
            SimPVA      = new PVArray[ReadFarmSettings.SubArrayCount];
            SimInv      = new Inverter[ReadFarmSettings.SubArrayCount];
            SimACWiring = new ACWiring[ReadFarmSettings.SubArrayCount];

            // Initialize and Configure PVArray and Inverter Objects through their .CSYX file
            for (int SubArrayCount = 0; SubArrayCount < ReadFarmSettings.SubArrayCount; SubArrayCount++)
            {
                SimInv[SubArrayCount] = new Inverter();
                SimInv[SubArrayCount].Config(SubArrayCount + 1);
                SimPVA[SubArrayCount] = new PVArray();
                SimPVA[SubArrayCount].Config(SubArrayCount + 1);
                SimACWiring[SubArrayCount] = new ACWiring();

                // If 'at Pnom' specified for AC Loss Fraction in version 1.2.0
                if (string.Compare(ReadFarmSettings.CASSYSCSYXVersion, "1.2.0") >= 0 && ReadFarmSettings.GetInnerText("System", "ACWiringLossAtSTC", _Error: ErrLevel.WARNING) == "False")
                {
                    SimACWiring[SubArrayCount].Config(SubArrayCount + 1, SimInv[SubArrayCount].itsOutputVoltage, SimInv[SubArrayCount].outputPhases, SimInv[SubArrayCount].itsPNomArrayAC);
                }
                else
                {
                    SimACWiring[SubArrayCount].Config(SubArrayCount + 1, SimInv[SubArrayCount].itsOutputVoltage, SimInv[SubArrayCount].outputPhases, SimInv[SubArrayCount].itsMaxSubArrayACEff * SimPVA[SubArrayCount].itsPNomDCArray);
                }
                farmArea += SimPVA[SubArrayCount].itsRoughArea;
            }
        }
Beispiel #21
0
        // Gathering the tracker mode, and relevant operational limits, and tracking axis characteristics.
        public void Config()
        {
            switch (ReadFarmSettings.GetAttribute("O&S", "ArrayType", ErrLevel.FATAL))
            {
            case "Fixed Tilted Plane":
                itsTrackMode = TrackMode.NOAT;
                if (String.Compare(ReadFarmSettings.CASSYSCSYXVersion, "0.9.3") >= 0)
                {
                    SurfSlope   = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTiltFix", ErrLevel.FATAL));
                    SurfAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AzimuthFix", ErrLevel.FATAL));
                }
                else
                {
                    SurfSlope   = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTilt", ErrLevel.FATAL));
                    SurfAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "Azimuth", ErrLevel.FATAL));
                }
                break;

            case "Fixed Tilted Plane Seasonal Adjustment":
                itsTrackMode       = TrackMode.FTSA;
                SurfAzimuth        = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AzimuthSeasonal", ErrLevel.FATAL));
                itsSummerMonth     = DateTime.ParseExact(ReadFarmSettings.GetInnerText("O&S", "SummerMonth", _Error: ErrLevel.FATAL), "MMM", CultureInfo.CurrentCulture).Month;
                itsWinterMonth     = DateTime.ParseExact(ReadFarmSettings.GetInnerText("O&S", "WinterMonth", _Error: ErrLevel.FATAL), "MMM", CultureInfo.CurrentCulture).Month;
                itsSummerDay       = int.Parse(ReadFarmSettings.GetInnerText("O&S", "SummerDay", _Error: ErrLevel.FATAL));
                itsWinterDay       = int.Parse(ReadFarmSettings.GetInnerText("O&S", "WinterDay", _Error: ErrLevel.FATAL));
                itsPlaneTiltSummer = Util.DTOR * double.Parse(ReadFarmSettings.GetInnerText("O&S", "PlaneTiltSummer", _Error: ErrLevel.FATAL));
                itsPlaneTiltWinter = Util.DTOR * double.Parse(ReadFarmSettings.GetInnerText("O&S", "PlaneTiltWinter", _Error: ErrLevel.FATAL));

                // Assume the simualtion will begin when the array is in the summer tilt
                SurfSlope = itsPlaneTiltSummer;

                break;

            case "Unlimited Rows":
                itsTrackMode = TrackMode.NOAT;
                // Defining all the parameters for the shading of a unlimited row array configuration
                SurfSlope   = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTilt", ErrLevel.FATAL));
                SurfAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "Azimuth", ErrLevel.FATAL));
                break;

            case "Single Axis Elevation Tracking (E-W)":
                // Tracker Parameters
                itsTrackMode      = TrackMode.SAXT;
                itsTrackerAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AxisAzimuthSAET", ErrLevel.FATAL));
                itsTrackerSlope   = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AxisTiltSAET", ErrLevel.FATAL));

                // Operational Limits
                itsMinTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "MinTiltSAET", ErrLevel.FATAL));
                itsMaxTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "MaxTiltSAET", ErrLevel.FATAL));


                // Backtracking Options
                useBackTracking = Convert.ToBoolean(ReadFarmSettings.GetInnerText("O&S", "BacktrackOptSAET", ErrLevel.WARNING, _default: "false"));
                if (useBackTracking)
                {
                    itsTrackerPitch = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PitchSAET", ErrLevel.FATAL));
                    itsTrackerBW    = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "WActiveSAET", ErrLevel.FATAL));
                }
                break;

            case "Single Axis Horizontal Tracking (N-S)":
                // Tracker Parameters
                itsTrackMode      = TrackMode.SAXT;
                itsTrackerSlope   = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AxisTiltSAST", ErrLevel.FATAL));
                itsTrackerAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AxisAzimuthSAST", ErrLevel.FATAL));

                // Operational Limits
                itsMaxTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "RotationMaxSAST", ErrLevel.FATAL));


                // Backtracking Options
                useBackTracking = Convert.ToBoolean(ReadFarmSettings.GetInnerText("O&S", "BacktrackOptSAST", ErrLevel.WARNING, _default: "false"));
                if (useBackTracking)
                {
                    itsTrackerPitch = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PitchSAST", ErrLevel.FATAL));
                    itsTrackerBW    = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "WActiveSAST", ErrLevel.FATAL));
                }
                break;


            case "Tilt and Roll Tracking":
                // Tracker Parameters
                itsTrackMode      = TrackMode.SAXT;
                itsTrackerSlope   = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AxisTiltTART", ErrLevel.FATAL));
                itsTrackerAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AxisAzimuthTART", ErrLevel.FATAL));

                // Operational Limits
                itsMinRotationAngle = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "RotationMinTART", ErrLevel.FATAL));
                itsMaxRotationAngle = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "RotationMaxTART", ErrLevel.FATAL));

                break;

            case "Two Axis Tracking":
                itsTrackMode = TrackMode.TAXT;
                // Operational Limits
                itsMinTilt    = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "MinTiltTAXT", ErrLevel.FATAL));
                itsMaxTilt    = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "MaxTiltTAXT", ErrLevel.FATAL));
                itsAzimuthRef = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AzimuthRefTAXT", ErrLevel.FATAL));
                itsMinAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "MinAzimuthTAXT", ErrLevel.FATAL));
                itsMaxAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "MaxAzimuthTAXT", ErrLevel.FATAL));
                break;

            case "Azimuth (Vertical Axis) Tracking":
                itsTrackMode = TrackMode.AVAT;
                // Surface Parameters
                SurfSlope = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTiltAVAT", ErrLevel.FATAL));
                // Operational Limits
                itsAzimuthRef = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "AzimuthRefAVAT", ErrLevel.FATAL));
                itsMinAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "MinAzimuthAVAT", ErrLevel.FATAL));
                itsMaxAzimuth = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "MaxAzimuthAVAT", ErrLevel.FATAL));
                break;

            default:
                ErrorLogger.Log("No orientation and shading was specified by the user.", ErrLevel.FATAL);
                break;
            }
        }
Beispiel #22
0
        // Config manages calculations and initializations that need only to be run once
        public void Config()
        {
            bool useBifacial = Convert.ToBoolean(ReadFarmSettings.GetInnerText("Bifacial", "UseBifacialModel", ErrLevel.FATAL));

            if (useBifacial)
            {
                // Number of segments into which to divide up the ground [#]
                numGroundSegs = Util.NUM_GROUND_SEGS;

                switch (ReadFarmSettings.GetAttribute("O&S", "ArrayType", ErrLevel.FATAL))
                {
                // In all cases, pitch and clearance must be normalized to panel slope lengths
                case "Fixed Tilted Plane":
                    itsTrackMode = TrackMode.NOAT;
                    if (String.Compare(ReadFarmSettings.CASSYSCSYXVersion, "0.9.3") >= 0)
                    {
                        itsPanelTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTiltFix", ErrLevel.FATAL));
                    }
                    else
                    {
                        itsPanelTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTilt", ErrLevel.FATAL));
                    }
                    // itsPitch will be assigned in the below (numRows == 1) conditional
                    itsArrayBW   = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "CollBandWidthFix", ErrLevel.FATAL));
                    itsClearance = Convert.ToDouble(ReadFarmSettings.GetInnerText("Bifacial", "GroundClearance", ErrLevel.FATAL)) / itsArrayBW;
                    numRows      = 1;
                    break;

                case "Unlimited Rows":
                    itsTrackMode = TrackMode.NOAT;
                    itsPanelTilt = Util.DTOR * Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PlaneTilt", ErrLevel.FATAL));
                    itsArrayBW   = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "CollBandWidth", ErrLevel.FATAL));
                    itsPitch     = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "Pitch", ErrLevel.FATAL)) / itsArrayBW;
                    itsClearance = Convert.ToDouble(ReadFarmSettings.GetInnerText("Bifacial", "GroundClearance", ErrLevel.FATAL)) / itsArrayBW;
                    numRows      = int.Parse(ReadFarmSettings.GetInnerText("O&S", "RowsBlock", ErrLevel.FATAL));
                    break;

                case "Single Axis Elevation Tracking (E-W)":
                    itsTrackMode = TrackMode.SAXT;
                    itsArrayBW   = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "WActiveSAET", ErrLevel.FATAL));
                    itsPitch     = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PitchSAET", ErrLevel.FATAL)) / itsArrayBW;
                    numRows      = int.Parse(ReadFarmSettings.GetInnerText("O&S", "RowsBlockSAET", ErrLevel.FATAL));
                    break;

                case "Single Axis Horizontal Tracking (N-S)":
                    itsTrackMode = TrackMode.SAXT;
                    itsArrayBW   = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "WActiveSAST", ErrLevel.FATAL));
                    itsPitch     = Convert.ToDouble(ReadFarmSettings.GetInnerText("O&S", "PitchSAST", ErrLevel.FATAL)) / itsArrayBW;
                    numRows      = int.Parse(ReadFarmSettings.GetInnerText("O&S", "RowsBlockSAST", ErrLevel.FATAL));
                    break;

                default:
                    ErrorLogger.Log("Bifacial is not supported for the selected orientation and shading.", ErrLevel.FATAL);
                    break;
                }

                transFactor = Convert.ToDouble(ReadFarmSettings.GetInnerText("Bifacial", "PanelTransFactor", ErrLevel.FATAL));

                if (numRows == 1)
                {
                    // Pitch is needed for a single row because of ground patch calculations and geometry. Take value 100x greater than array bandwidth.
                    itsPitch   = 100;
                    itsRowType = RowType.SINGLE;
                }
                else
                {
                    itsRowType = RowType.INTERIOR;
                }

                // Initialize arrays
                frontGroundSH = new int[numGroundSegs];
                rearGroundSH  = new int[numGroundSegs];

                frontSkyViewFactors = new double[numGroundSegs];
                rearSkyViewFactors  = new double[numGroundSegs];

                frontGroundGHI = new double[numGroundSegs];
                rearGroundGHI  = new double[numGroundSegs];

                // Calculate sky view factors for diffuse shading. Stays constant for non-tracking systems, so done here in Config()
                if (itsTrackMode == TrackMode.NOAT)
                {
                    CalcSkyViewFactors();
                }
            }
        }
Beispiel #23
0
        // Obtaining and Setting efficiency curve values from .CSYX file
        public void ConfigEffCurves(int ArrayNum, bool threeCurves)
        {
            // Configuration begins with a check if the Inverter has three efficiency curves or just one
            // Once determined, relevant values are collected from the .CSYX file
            if (threeCurves)
            {
                // Initiating an Array to hold Interpolated Values and the three voltage levels
                itsPresentEfficiencies[0] = new double[3];             // To hold the three voltage levels [Array, V]
                itsPresentEfficiencies[1] = new double[3];             // To hold the three efficiencies from interpolation [Array, %, Computed in Calculate Method]

                // Getting the Low, Medium and High Voltage Values used in the Curve
                itsLowVoltage = double.Parse(ReadFarmSettings.GetAttribute("Inverter", "Voltage", _Adder: "/Efficiency/Low", _ArrayNum: ArrayNum));
                itsPresentEfficiencies[0][0] = itsLowVoltage;
                itsMedVoltage = double.Parse(ReadFarmSettings.GetAttribute("Inverter", "Voltage", _Adder: "/Efficiency/Med", _ArrayNum: ArrayNum));
                itsPresentEfficiencies[0][1] = itsMedVoltage;
                itsHighVoltage = double.Parse(ReadFarmSettings.GetAttribute("Inverter", "Voltage", _Adder: "/Efficiency/High", _ArrayNum: ArrayNum));
                itsPresentEfficiencies[0][2] = itsHighVoltage;

                // Setting the lowest efficiency (i.e. at Threshold Power)

                List <double> lowEffIn    = new List <double>();
                List <double> lowEffFrac  = new List <double>();
                List <double> medEffIn    = new List <double>();
                List <double> medEffFrac  = new List <double>();
                List <double> highEffIn   = new List <double>();
                List <double> highEffFrac = new List <double>();
                double        effInPlaceholder;
                double        effFracPlaceholder;

                lowEffIn.Add(itsThresholdPwr * itsNumInverters);
                lowEffFrac.Add(0);
                medEffIn.Add(itsThresholdPwr * itsNumInverters);
                medEffFrac.Add(0);
                highEffIn.Add(itsThresholdPwr * itsNumInverters);
                highEffFrac.Add(0);
                // Get Low Voltage Efficiency Curve
                for (int eff = 1; eff < 8; eff++)
                {
                    effIn   = double.TryParse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/Low/IN" + (eff + 1).ToString(), _ArrayNum: ArrayNum, _default: null), out effInPlaceholder);
                    effFrac = double.TryParse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/Low/Effic" + (eff + 1).ToString(), _ArrayNum: ArrayNum, _default: null), out effFracPlaceholder);
                    if (effIn && effFrac)
                    {
                        ErrorLogger.Assert("The Inverter Efficiency Curve is Incorrectly defined. Check Inverter in Sub-Array " + ArrayNum + ".", double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/Low/Effic" + (eff + 1).ToString(), _ArrayNum: ArrayNum)) < 100, ErrLevel.FATAL);
                        lowEffIn.Add(effInPlaceholder * itsNumInverters * 1000);
                        lowEffFrac.Add(effInPlaceholder * effFracPlaceholder * itsNumInverters * 10);
                    }
                }
                itsLowEff[0] = lowEffIn.ToArray();
                itsLowEff[1] = lowEffFrac.ToArray();

                // Get Med Voltage Efficiency Curve
                for (int eff = 1; eff < 8; eff++)
                {
                    effIn   = double.TryParse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/Med/IN" + (eff + 1).ToString(), _ArrayNum: ArrayNum, _default: null), out effInPlaceholder);
                    effFrac = double.TryParse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/Med/Effic" + (eff + 1).ToString(), _ArrayNum: ArrayNum, _default: null), out effFracPlaceholder);
                    if (effIn && effFrac)
                    {
                        ErrorLogger.Assert("The Inverter Efficiency Curve is Incorrectly defined. Check Inverter in Sub-Array " + ArrayNum + ".", double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/Med/Effic" + (eff + 1).ToString(), _ArrayNum: ArrayNum)) < 100, ErrLevel.FATAL);
                        medEffIn.Add(effInPlaceholder * itsNumInverters * 1000);
                        medEffFrac.Add(effInPlaceholder * effFracPlaceholder * itsNumInverters * 10);
                    }
                }
                itsMedEff[0] = medEffIn.ToArray();
                itsMedEff[1] = medEffFrac.ToArray();

                // Get High Voltage Efficiency Curve
                for (int eff = 1; eff < 8; eff++)
                {
                    effIn   = double.TryParse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/High/IN" + (eff + 1).ToString(), _ArrayNum: ArrayNum, _default: null), out effInPlaceholder);
                    effFrac = double.TryParse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/High/Effic" + (eff + 1).ToString(), _ArrayNum: ArrayNum, _default: null), out effFracPlaceholder);
                    if (effIn && effFrac)
                    {
                        ErrorLogger.Assert("The Inverter Efficiency Curve is Incorrectly defined. Check Inverter in Sub-Array " + ArrayNum + ".", double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/High/Effic" + (eff + 1).ToString(), _ArrayNum: ArrayNum)) < 100, ErrLevel.FATAL);
                        highEffIn.Add(effInPlaceholder * itsNumInverters * 1000);
                        highEffFrac.Add(effInPlaceholder * effFracPlaceholder * itsNumInverters * 10);
                    }
                }
                itsHighEff[0] = highEffIn.ToArray();
                itsHighEff[1] = highEffFrac.ToArray();
            }
            else
            {
                // The Inverter only has one Efficiency Curve
                // Setting the lowest efficiency (i.e. at Threshold Power)
                itsOnlyEff[0][0] = itsThresholdPwr * itsNumInverters;
                itsOnlyEff[1][0] = 0;

                // Go through all .CSYX Nodes with Efficiency values and assign them into Array
                for (int eff = 1; eff < itsOnlyEff[0].Length; eff++)
                {
                    ErrorLogger.Assert("The Inverter Efficiency Curve is Incorrectly defined. Check Inverter in Sub-Array " + ArrayNum + ".", double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/EffCurve/Effic." + (eff + 1).ToString(), _ArrayNum: ArrayNum)) < 100, ErrLevel.FATAL);
                    itsOnlyEff[0][eff] = double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/EffCurve/IN" + (eff + 1).ToString(), _ArrayNum: ArrayNum, _default: itsNomOutputPwr.ToString())) * itsNumInverters * 1000;
                    itsOnlyEff[1][eff] = itsOnlyEff[0][eff] * double.Parse(ReadFarmSettings.GetInnerText("Inverter", "Efficiency/EffCurve/Effic." + (eff + 1).ToString(), _ArrayNum: ArrayNum, _Error: ErrLevel.FATAL)) / 100;
                }
            }
        }
Beispiel #24
0
        // Calculate manages calculations that need to be run for each time step
        public void Calculate
        (
            double PanelTilt                        // The angle between the surface tilt of the module and the ground [radians]
            , double Clearance                      // Array ground clearance [m]
            , double HDif                           // Diffuse horizontal irradiance [W/m2]
            , double TDifRef                        // Front reflected diffuse irradiance [W/m2]
            , double HGlo                           // Horizontal global irradiance [W/m2]
            , double[] frontGroundGHI               // Global irradiance for each of the ground segments to front of the row [W/m2]
            , double[] rearGroundGHI                // Global irradiance for each of the ground segments to rear of the row [W/m2]
            , double aveGroundGHI                   // Average global irradiance on ground segment to the rear of row [W/m2]
            , int month                             // Current month, used for getting albedo value [#]
            , double siteAlbedo                     // Site albedo (used only if inter-row albedo is set to site albedo) [#]
            , double measAlbedo                     // Measured albedo read from climate file, if available [#]
            , double backSH                         // Fraction of the back surface of the PV array that is unshaded [#]
            , double TDir                           // Back tilted beam irradiance [W/m2]
            , DateTime ts                           // Time stamp analyzed, used for printing .csv files
        )
        {
            // For tracking systems, panel tilt and ground clearance will change at each time step
            itsPanelTilt = PanelTilt;
            itsClearance = Clearance / itsArrayBW;           // Convert to panel slope lengths

            int numGroundSegs = Util.NUM_GROUND_SEGS;

            double h = Math.Sin(itsPanelTilt);               // Vertical height of sloped PV panel [panel slope lengths]
            double b = Math.Cos(itsPanelTilt);               // Horizontal distance from front of panel to back of panel [panel slope lengths]

            // Calculate x, y coordinates of bottom and top edges of PV row behind the current PV row so that portions of sky and ground viewed by
            // the PV cell may be determined. Coordinates are relative to (0,0) being the ground point below the lower front edge of current PV row.
            // The row behind the current row is in the positive x direction.
            double bottomX = itsPitch;                       // x value for point on bottom edge of PV panel behind current row
            double bottomY = itsClearance;                   // y value for point on bottom edge of PV panel behind current row
            double topX    = bottomX + b;                    // x value for point on top edge of PV panel behind current row
            double topY    = bottomY + h;                    // y value for point on top edge of PV panel behind current row

            // Get albedo value for the month
            if (ReadFarmSettings.GetAttribute("BifAlbedo", "Frequency", ErrLevel.WARNING) == "From Climate File")
            {
                Albedo = measAlbedo;
            }
            else if (ReadFarmSettings.GetAttribute("BifAlbedo", "Frequency", ErrLevel.WARNING) == "Site")
            {
                Albedo = siteAlbedo;
            }
            else
            {
                Albedo = itsMonthlyAlbedo[month];
            }

            // Accumulate diffuse, reflected, and beam irradiance components for each cell row over its field of view of PI radians
            for (int i = 0; i < numCellRows; i++)
            {
                double cellX = b * (i + 0.5) / numCellRows;                                     // x value for location of cell
                double cellY = itsClearance + h * (i + 0.5) / numCellRows;                      // y value for location of cell

                double elevUp   = 0.0;                                                          // Elevation angle from PV cell to top of PV panel
                double elevDown = 0.0;                                                          // Elevation angle from PV cell to bottom of PV panel
                if (itsRowType == RowType.INTERIOR)
                {
                    elevUp   = Math.Atan((topY - cellY) / (topX - cellX));
                    elevDown = Math.Atan((cellY - bottomY) / (bottomX - cellX));
                }

                int stopSky     = Convert.ToInt32((itsPanelTilt - elevUp) * Util.RTOD);         // Last whole degree in arc range that sees sky; first is 0 [degrees]
                int startGround = Convert.ToInt32((itsPanelTilt + elevDown) * Util.RTOD);       // First whole degree in arc range that sees ground; last is 180 [degrees]

                // Compute sky diffuse component
                backDif[i] = RadiationProc.GetViewFactor(0, stopSky * Util.DTOR) * HDif;

                // Compute front surface reflected component
                if (itsRowType == RowType.INTERIOR)
                {
                    backFroRef[i] = RadiationProc.GetViewFactor(stopSky * Util.DTOR, startGround * Util.DTOR) * TDifRef;
                }

                backGroRef[i] = 0;
                // Add ground reflected component
                for (int j = startGround; j < 180; j++)
                {
                    // Get start and ending elevations for this (j, j + 1) pair
                    double startElevDown = elevDown + (j - startGround) * Util.DTOR;
                    double stopElevDown  = elevDown + (j + 1 - startGround) * Util.DTOR;

                    // Projection onto ground in positive x direction
                    double projX2 = cellX + cellY / Math.Tan(startElevDown);
                    double projX1 = cellX + cellY / Math.Tan(stopElevDown);

                    // Initialize and get actualGroundGHI value
                    double actualGroundGHI = 0;
                    if (Math.Abs(projX1 - projX2) > 0.99 * itsPitch)
                    {
                        if (itsRowType == RowType.SINGLE)
                        {
                            // Use measured GHI if projection approximates or exceeds the pitch
                            actualGroundGHI = HGlo;
                        }
                        else
                        {
                            // Use average GHI if projection approximates or exceeds the pitch
                            actualGroundGHI = aveGroundGHI;
                        }
                    }
                    else
                    {
                        // Normalize projections and multiply by n
                        projX1 = numGroundSegs * projX1 / itsPitch;
                        projX2 = numGroundSegs * projX2 / itsPitch;

                        if (itsRowType == RowType.SINGLE && ((Math.Abs(projX1) > numGroundSegs - 1) || (Math.Abs(projX2) > numGroundSegs - 1)))
                        {
                            // Use measured GHI if projection exceeds the pitch
                            actualGroundGHI = HGlo;
                        }
                        else
                        {
                            while (projX1 < -numGroundSegs || projX2 < -numGroundSegs)
                            {
                                projX1 += numGroundSegs;
                                projX2 += numGroundSegs;
                            }
                            while (projX1 >= numGroundSegs || projX2 >= numGroundSegs)
                            {
                                projX1 -= numGroundSegs;
                                projX2 -= numGroundSegs;
                            }

                            // Determine indices (truncate values) for use with groundGHI arrays
                            int index1 = Convert.ToInt32(Math.Floor(projX1 + numGroundSegs) - numGroundSegs);
                            int index2 = Convert.ToInt32(Math.Floor(projX2 + numGroundSegs) - numGroundSegs);

                            if (index1 == index2)
                            {
                                // Use single value if projection falls within a single segment of ground
                                if (index1 < 0)
                                {
                                    actualGroundGHI = frontGroundGHI[index1 + numGroundSegs];
                                }
                                else
                                {
                                    actualGroundGHI = rearGroundGHI[index1];
                                }
                            }
                            else
                            {
                                // Sum the irradiances on the ground if the projection falls across multiple segments
                                for (int k = index1; k <= index2; k++)
                                {
                                    if (k == index1)
                                    {
                                        if (k < 0)
                                        {
                                            actualGroundGHI += frontGroundGHI[k + numGroundSegs] * (k + 1.0 - projX1);
                                        }
                                        else
                                        {
                                            actualGroundGHI += rearGroundGHI[k] * (k + 1.0 - projX1);
                                        }
                                    }
                                    else if (k == index2)
                                    {
                                        if (k < 0)
                                        {
                                            actualGroundGHI += frontGroundGHI[k + numGroundSegs] * (projX2 - k);
                                        }
                                        else
                                        {
                                            actualGroundGHI += rearGroundGHI[k] * (projX2 - k);
                                        }
                                    }
                                    else
                                    {
                                        if (k < 0)
                                        {
                                            actualGroundGHI += frontGroundGHI[k + numGroundSegs];
                                        }
                                        else
                                        {
                                            actualGroundGHI += rearGroundGHI[k];
                                        }
                                    }
                                }
                                // Get irradiance on ground in the 1 degree field of view
                                actualGroundGHI /= projX2 - projX1;
                            }
                        }
                    }
                    backGroRef[i] += RadiationProc.GetViewFactor(j * Util.DTOR, (j + 1) * Util.DTOR) * actualGroundGHI * Albedo;
                }

                double cellShade = 0.0;
                if (itsRowType == RowType.INTERIOR)
                {
                    // Cell is fully shaded if >= 1, fully unshaded if <= 0, otherwise fractionally shaded
                    cellShade = (1.0 - backSH) * numCellRows - i;
                    cellShade = Math.Min(cellShade, 1.0);
                    cellShade = Math.Max(cellShade, 0.0);
                }

                // Compute beam component, corrected for back shading
                backDir[i] = TDir * (1.0 - cellShade);

                // Correct each component for AOI and structure shading losses
                backDif[i]    = backDif[i] * IAMDif * (1.0 - structLossFactor);
                backFroRef[i] = backFroRef[i] * IAMRef * (1.0 - structLossFactor);
                backGroRef[i] = backGroRef[i] * IAMRef * (1.0 - structLossFactor);
                backDir[i]    = backDir[i] * IAMDir * (1.0 - structLossFactor);

                // Sum all components to get global back irradiance
                backGlo[i] = backDif[i] + backFroRef[i] + backGroRef[i] + backDir[i];
            }

            BDif    = 0;
            BFroRef = 0;
            BGroRef = 0;
            BDir    = 0;

            double maxGlo = backGlo[0];
            double minGlo = backGlo[0];

            for (int i = 0; i < numCellRows; i++)
            {
                // Calculate mean irradiance components
                BDif    += backDif[i] / numCellRows;
                BFroRef += backFroRef[i] / numCellRows;
                BGroRef += backGroRef[i] / numCellRows;
                BDir    += backDir[i] / numCellRows;

                // Find the max and min global irradiance values
                maxGlo = Math.Max(maxGlo, backGlo[i]);
                minGlo = Math.Min(minGlo, backGlo[i]);
            }
            BGlo = BDif + BFroRef + BGroRef + BDir;

            // Calculate the homogeneity of values as the range normalized by the sum
            IrrInhomogeneity = (BGlo > 0) ? (maxGlo - minGlo) / BGlo : 0;

            // Option to print details of the model in .csv files. Only recommended for single day simulations.
            // PrintModel(ts);
        }