public ArraySimulationStepOutput() { Strings = new ArraySimStringOutput[0]; }
/// <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; }