Example #1
0
        private void TimeAveragedSim()
        {
            // input time range; all other inputs come from simInput
            DateTime utcStart = dateTimePicker1.Value.AddHours(-simInput.TimezoneOffsetHours);
            DateTime utcEnd = dateTimePicker2.Value.AddHours(-simInput.TimezoneOffsetHours);

            // step-by-step output
            TextWriter csv = new StreamWriter("../../../../output.csv");
            csv.WriteLine("time_utc,insolation_w,output_w");

            // average output
            var simAvg = new ArraySimulationStepOutput();

            // simulate in 10-minute intervals
            InitSimulator();
            int nsim = 0;
            for (DateTime time = utcStart; time <= utcEnd; time = time.AddMinutes(10), nsim++) {
                simInput.Utc = time;
                simInputControls.UpdateView();
                ArraySimulationStepOutput simOutput = simulator.Simulate(simInput);

                // averate the outputs
                if (nsim > 0) {
                    Debug.Assert(simAvg.ArrayArea == simOutput.ArrayArea);
                }
                simAvg.ArrayArea = simOutput.ArrayArea;
                simAvg.ArrayLitArea += simOutput.ArrayLitArea;
                simAvg.WattsInsolation += simOutput.WattsInsolation;
                simAvg.WattsOutputByCell += simOutput.WattsOutputByCell;
                simAvg.WattsOutput += simOutput.WattsOutput;

                // debug output
                csv.WriteLine(time + "," + simOutput.WattsInsolation + "," + simOutput.WattsOutput);
            }
            csv.Close();

            // show the average output
            simAvg.ArrayLitArea /= nsim;
            simAvg.WattsInsolation /= nsim;
            simAvg.WattsOutputByCell /= nsim;
            simAvg.WattsOutput /= nsim;
            Debug.WriteLine("Array time-averaged simulation output");
            Debug.WriteLine("   ... " + simAvg.ArrayArea + " m^2 total cell area");
            Debug.WriteLine("   ... " + simAvg.ArrayLitArea + " m^2 exposed to sunlight");
            Debug.WriteLine("   ... " + simAvg.WattsInsolation + " W insolation");
            Debug.WriteLine("   ... " + simAvg.WattsOutputByCell + " W output (assuming mppt per cell)");
            Debug.WriteLine("   ... " + simAvg.WattsOutput + " W output");
        }
        /// <summary>
        /// Reads the compute textures from OpenGL.
        /// This gives insolation for each cell.
        /// 
        /// Uses this to calculate IV curves, etc, and ultimately array power.
        /// </summary>
        private ArraySimulationStepOutput AnalyzeComputeTex(ArraySpec array, double wPerM2Insolation, double wPerM2Iindirect, double encapLoss, double cTemp)
        {
            Color[] texColors = ReadColorTexture(FramebufferAttachment.ColorAttachment0);
            float[] texWattsIn = ReadFloatTexture(FramebufferAttachment.ColorAttachment1, 0.0001);
            double arrayDimM = ComputeArrayMaxDimension(array);
            double m2PerPixel = arrayDimM * arrayDimM / COMPUTE_TEX_SIZE / COMPUTE_TEX_SIZE;
            float[] texArea = ReadFloatTexture(FramebufferAttachment.ColorAttachment2, m2PerPixel / 4);
            double dbgmin = texArea[0], dbgmax = texArea[0], dbgavg = 0;
            for (int i = 0; i < texArea.Length; i++)
            {
                dbgmin = Math.Min(dbgmin, texArea[i]);
                dbgmax = Math.Max(dbgmax, texArea[i]);
                dbgavg += texArea[i];
            }
            dbgavg /= texArea.Length;

            // find the cell at each fragment...
            int ncells = 0;
            var cells = new List<ArraySpec.Cell>();
            var colorToId = new Dictionary<Color, int>();
            foreach (ArraySpec.CellString cellStr in array.Strings) {
                foreach (ArraySpec.Cell cell in cellStr.Cells) {
                    cells.Add(cell);
                    colorToId.Add(cell.Color, ncells);
                    ncells++;
                }
            }

            // finally, find the area and insolation for each cell
            double[] wattsIn = new double[ncells];
            double[] areas = new double[ncells];
            double wattsInUnlinked = 0, areaUnlinked = 0;
            for (int i = 0; i < computeWidth * computeHeight; i++) {
                Color color = texColors[i];
                if (ColorUtils.IsGrayscale(color)) continue;
                if (colorToId.ContainsKey(color)) {
                    int id = colorToId[color];
                    wattsIn[id] += texWattsIn[i];
                    areas[id] += texArea[i];
                } else {
                    wattsInUnlinked += texWattsIn[i];
                    areaUnlinked += texArea[i];
                }
            }
            if (areaUnlinked > 0 || wattsInUnlinked > 0) {
                Logger.warn("Found texels that are not grayscale, " +
                    "but also doesn't correspond to any cell. Have you finished your layout?" +
                    "\n\tTotal of {0}m^2 cell area not in any string, with {1}W insolation.",
                    areaUnlinked,wattsInUnlinked);
            }

            // add indirect insolation, encapsulation loss
            for (int i = 0; i < ncells; i++) {
                wattsIn[i] += array.CellSpec.Area * wPerM2Iindirect;
                wattsIn[i] *= (1.0 - encapLoss);
            }

            // find totals
            double totalArea = 0, totalWattsIn = 0;
            for (int i = 0; i < ncells; i++) {
                totalWattsIn += wattsIn[i];
                totalArea += areas[i];
                Debug.WriteLine("cell {0}: {1}W, {2}m^2", i, wattsIn[i], areas[i]);
            }
            Debug.WriteLine("total: {0}W, {1}m^2", totalWattsIn, totalArea);

            // MPPT sweeps, for each cell and each string.
            // Inputs:
            CellSpec cellSpec = array.CellSpec;
            int nstrings = array.Strings.Count;
            // Outputs:
            double totalWattsOutByCell = 0;
            double totalWattsOutByString = 0;
            var strings = new ArraySimStringOutput[nstrings];
            int cellIx = 0;
            for(int i = 0; i < nstrings; i++){
                var cellStr = array.Strings[i];
                double stringWattsIn = 0, stringWattsOutByCell = 0, stringLitArea = 0;

                // per-cell sweeps
                var cellSweeps = new IVTrace[cellStr.Cells.Count];
                for(int j = 0; j < cellStr.Cells.Count; j++){
                    double cellWattsIn = wattsIn[cellIx++];
                    double cellInsolation = cellWattsIn / cellSpec.Area;
                    IVTrace cellSweep = CellSimulator.CalcSweep(cellSpec, cellInsolation, cTemp);
                    cellSweeps[j] = cellSweep;

                    stringWattsIn += cellWattsIn;
                    stringWattsOutByCell += cellSweep.Pmp;
                    totalWattsOutByCell += cellSweep.Pmp;

                    // shading stats
                    stringLitArea += areas[i];
                }

                // string sweep
                strings[i] = new ArraySimStringOutput();
                strings[i].WattsIn = stringWattsIn;
                strings[i].WattsOutputByCell = stringWattsOutByCell;
                IVTrace stringSweep = StringSimulator.CalcStringIV(cellStr, cellSweeps, array.BypassDiodeSpec);
                strings[i].WattsOutput = stringSweep.Pmp;
                strings[i].IVTrace = stringSweep;

                // higher-level string info
                strings[i].String = cellStr;
                strings[i].Area = cellStr.Cells.Count*cellSpec.Area;
                strings[i].AreaShaded = strings[i].Area - stringLitArea;
                IVTrace cellSweepIdeal = CellSimulator.CalcSweep(cellSpec,wPerM2Insolation,cTemp);
                strings[i].WattsOutputIdeal = cellSweepIdeal.Pmp * cellStr.Cells.Count;

                // total array power
                totalWattsOutByString += stringSweep.Pmp;
            }

            ArraySimulationStepOutput output = new ArraySimulationStepOutput();
            output.ArrayArea = ncells * cellSpec.Area;
            output.ArrayLitArea = totalArea;
            output.WattsInsolation = totalWattsIn;
            output.WattsOutputByCell = totalWattsOutByCell;
            output.WattsOutput = totalWattsOutByString;
            output.Strings = strings;
            return output;
        }