예제 #1
0
        /// <summary>
        /// Renders the array from the sun's point of view, into several buffers:
        /// one for cell id (texture map), one for insolation, and one for area.
        /// 
        /// After this step, results be read using OpenGL ReadBuffer and analyzed.
        /// </summary>
        public void ComputeRender(ArraySpec array, Vector3 sunDir)
        {
            Debug.WriteLine("rendering insolation+cells into a "
                + computeWidth + "x" + computeWidth + " fbo");

            // gl state
            GL.UseProgram(shaderProg);
            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, fboWatts);
            GL.DrawBuffers(3, new DrawBuffersEnum[]{
                (DrawBuffersEnum)FramebufferAttachment.ColorAttachment0Ext,
                (DrawBuffersEnum)FramebufferAttachment.ColorAttachment1Ext,
                (DrawBuffersEnum)FramebufferAttachment.ColorAttachment2Ext});

            GL.BindTexture(TextureTarget.Texture2D, texArray);
            GL.Viewport(0, 0, computeWidth, computeHeight);
            GL.ClearColor(Color.White);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            Vector3 arrayCenter = ComputeArrayCenter(array);
            double arrayMaxDimension = ComputeArrayMaxDimension(array);
            SetCameraSunPOV(sunDir, arrayCenter, arrayMaxDimension);

            //render
            MeshSprite sprite = new MeshSprite(array.Mesh);
            sprite.PushTransform();
            sprite.Render();
            sprite.PopTransform();
        }
예제 #2
0
        public ArrayLayoutForm(ArraySpec spec)
        {
            Debug.Assert(spec != null);
            this.array = spec;

            InitializeComponent();
            UpdateView();
        }
예제 #3
0
        private IList <TSpec> ReadTSpecs()
        {
            var tspecs = new List <TSpec>();

            while (true)
            {
                SkipWhite();
                switch (PeekChar())
                {
                case '[':     // SZArray, Array, or GenericInst
                    ReadChar();
                    SkipWhite();
                    var peeked = PeekChar();
                    if (peeked == ']')
                    {
                        // SZ array
                        Verify(ReadChar() == ']', "Expected ']'");
                        tspecs.Add(SZArraySpec.Instance);
                    }
                    else if (peeked == '*' || peeked == ',' || peeked == '-' || char.IsDigit((char)peeked))
                    {
                        // Array

                        var arraySpec = new ArraySpec();
                        arraySpec.rank = 0;
                        while (true)
                        {
                            SkipWhite();
                            var c = PeekChar();
                            if (c == '*')
                            {
                                ReadChar();
                            }
                            else if (c == ',' || c == ']')
                            {
                            }
                            else if (c == '-' || char.IsDigit((char)c))
                            {
                                var  lower = ReadInt32();
                                uint?size;
                                SkipWhite();
                                Verify(ReadChar() == '.', "Expected '.'");
                                Verify(ReadChar() == '.', "Expected '.'");
                                if (PeekChar() == '.')
                                {
                                    ReadChar();
                                    size = null;
                                }
                                else
                                {
                                    SkipWhite();
                                    if (PeekChar() == '-')
                                    {
                                        var upper = ReadInt32();
                                        Verify(upper >= lower, "upper < lower");
                                        size = (uint)(upper - lower + 1);
                                        Verify(size.Value != 0 && size.Value <= 0x1FFFFFFF, "Invalid size");
                                    }
                                    else
                                    {
                                        var upper = ReadUInt32();
                                        var lsize = upper - lower + 1;
                                        Verify(lsize > 0 && lsize <= 0x1FFFFFFF, "Invalid size");
                                        size = (uint)lsize;
                                    }
                                }
                                if (arraySpec.lowerBounds.Count == arraySpec.rank)
                                {
                                    arraySpec.lowerBounds.Add(lower);
                                }
                                if (size.HasValue && arraySpec.sizes.Count == arraySpec.rank)
                                {
                                    arraySpec.sizes.Add(size.Value);
                                }
                            }
                            else
                            {
                                Verify(false, "Unknown char");
                            }

                            arraySpec.rank++;
                            SkipWhite();
                            if (PeekChar() != ',')
                            {
                                break;
                            }
                            ReadChar();
                        }

                        Verify(ReadChar() == ']', "Expected ']'");
                        tspecs.Add(arraySpec);
                    }
                    else
                    {
                        // Generic args

                        var ginstSpec = new GenericInstSpec();
                        while (true)
                        {
                            SkipWhite();
                            peeked = PeekChar();
                            var needSeperators = peeked == '[';
                            if (peeked == ']')
                            {
                                break;
                            }
                            Verify(!needSeperators || ReadChar() == '[', "Expected '['");
                            ginstSpec.args.Add(ReadType(needSeperators));
                            SkipWhite();
                            Verify(!needSeperators || ReadChar() == ']', "Expected ']'");
                            SkipWhite();
                            if (PeekChar() != ',')
                            {
                                break;
                            }
                            ReadChar();
                        }

                        Verify(ReadChar() == ']', "Expected ']'");
                        tspecs.Add(ginstSpec);
                    }
                    break;

                case '&':     // ByRef
                    ReadChar();
                    tspecs.Add(ByRefSpec.Instance);
                    break;

                case '*':     // Ptr
                    ReadChar();
                    tspecs.Add(PtrSpec.Instance);
                    break;

                default:
                    return(tspecs);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Gets the centerpoint of each cell in the texture 
        /// that has been wired in the current string, in order, 
        /// in screen (layout control pixel, not texel) coordinates.
        /// </summary>
        private PointF[] ComputeCellCenterpoints(ArraySpec.CellString cellString)
        {
            if (cellString == null) {
                return new PointF[0];
            }

            SizeF arraySize = GetScaledArraySize();
            float scale = arraySize.Width / Array.LayoutTexture.Width;

            int n = cellString.Cells.Count;
            PointF[] points = new PointF[n];
            for (int i = 0; i < n; i++) {
                ArraySpec.Cell cell = cellString.Cells[i];
                int sx = 0, sy = 0;
                foreach (Pair<int> xy in cell.Pixels) {
                    sx += xy.First;
                    sy += xy.Second;
                }
                int m = cell.Pixels.Count;
                points[i] = new PointF(
                    (float)sx / m * scale,
                    (float)sy / m * scale);
            }
            return points;
        }
예제 #5
0
 private void ClickCell(ArraySpec.Cell cell)
 {
     // either add it to the current string, or remove it if it's already there
     if (!CellString.Cells.Remove(cell)) {
         CellString.Cells.Add(cell);
     } else {
         // prune bypass diodes
         CellString.BypassDiodes.RemoveAll((diode) => {
             return diode.CellIxs.First >= CellString.Cells.Count ||
                 diode.CellIxs.Second >= CellString.Cells.Count;
         });
     }
 }
예제 #6
0
 void AddArray(ArraySpec array)
 {
     if (array_spec == null)
         array_spec = new List<ArraySpec>();
     array_spec.Add(array);
 }
        public static IEnumerable <TestCaseData> SpecificationExtensionsTestIsSameCaseSource()
        {
            // single spec types
            var specFirstNull             = new FirstNameSpec(null);
            var specFirstNull2            = new FirstNameSpec(null);
            var specFirstBob              = new FirstNameSpec("bob");
            var specFirstBob2             = new FirstNameSpec("bob");
            var specFirstBobbette         = new FirstNameSpec("bobbette");
            var specFirstAndLastBob       = new FirstAndLastNameSpec("bob", "le");
            var specFirstAndLastBob2      = new FirstAndLastNameSpec("bob", "le");
            var specFirstAndLastBobbbette = new FirstAndLastNameSpec("bobbette", "le");
            var specLastBob = new LastNameSpec("bob");

            yield return(new TestCaseData("Check on null type", specFirstBob, null, false));

            yield return(new TestCaseData("Check non reference type", specFirstBob, "dinge", false));

            yield return(new TestCaseData("SameReference", specFirstBob, specFirstBob, true));

            yield return(new TestCaseData("Different type", specFirstBob, specLastBob, false));

            yield return(new TestCaseData("Same single content (null)", specFirstNull, specFirstNull2, true));

            yield return(new TestCaseData("Same single content", specFirstBob, specFirstBob2, true));

            yield return(new TestCaseData("Same multiple content", specFirstAndLastBob, specFirstAndLastBob2, true));

            yield return(new TestCaseData("Different single content", specFirstBob, specFirstBobbette, false));

            // operator specs
            var orSpecBob   = new OrSpecification <Sample>(specFirstBob, specFirstBob2);
            var orSpecBob2  = new OrSpecification <Sample>(specFirstBob, specFirstBob2);
            var orSpecBob3  = new OrSpecification <Sample>(specFirstBob, specLastBob);
            var andSpecBob  = new AndSpecification <Sample>(specFirstBob, specFirstBob);
            var andSpecBob2 = new AndSpecification <Sample>(specFirstBob, specFirstBob2);
            var andSpecBob3 = new AndSpecification <Sample>(specFirstBob, specLastBob);

            yield return(new TestCaseData("OR Same containing specs", orSpecBob, orSpecBob2, true));

            yield return(new TestCaseData("Or Different containing specs", orSpecBob, orSpecBob3, false));

            yield return(new TestCaseData("And Same containing specs", andSpecBob, andSpecBob2, true));

            yield return(new TestCaseData("And Different containing specs", andSpecBob, andSpecBob3, false));

            // array specs: value compares
            var array         = new int[] { 1, 2, 3 };
            var arraySpecNull = new ArraySpec <int>(null);
            var arraySpec     = new ArraySpec <int>(array);
            var arraySpec2    = new ArraySpec <int>(array);
            var arraySpec3    = new ArraySpec <int>(new int[] { 1, 2, 3 });
            var arraySpec4    = new ArraySpec <int>(new int[] { 1, 2, 3, 4 });

            yield return(new TestCaseData("Array - same array", arraySpec, arraySpec2, true));

            yield return(new TestCaseData("Array - different array - same content", arraySpec, arraySpec3, true));

            yield return(new TestCaseData("Array - different array - different content", arraySpec, arraySpec4, false));

            yield return(new TestCaseData("Array - different array - different content (null)", arraySpec, arraySpecNull, false));

            yield return(new TestCaseData("Array(obj) - same array", arraySpec, arraySpec2, true));

            // array specs: object compares
            var sample               = new Sample("le", "bob");
            var arraySpecSample      = new ArraySpec <Sample>(new Sample[] { sample, sample });
            var arraySpecSample2     = new ArraySpec <Sample>(new Sample[] { sample, sample });
            var arraySpecSampleNull  = new ArraySpec <Sample>(new Sample[] { sample, null, sample });
            var arraySpecSampleNull2 = new ArraySpec <Sample>(new Sample[] { sample, null, sample });
            var arraySpecObject      = new ArraySpec <object>(new object[] { "a", 1 });
            var arraySpecObject2     = new ArraySpec <object>(new object[] { "a", "b" });
            var arraySpecObject3     = new ArraySpec <object>(new object[] { "a", "c" });
            var arraySpecObjectnull  = new ArraySpec <object>(null);

            yield return(new TestCaseData("Array(obj) - different array - same content", arraySpecSample, arraySpecSample2, true));

            yield return(new TestCaseData("Array(obj) - different array - different content (null)", arraySpecSampleNull, arraySpecSampleNull2, false));

            yield return(new TestCaseData("Array(obj) - different array - different content (type)", arraySpecObject, arraySpecObject2, false));

            yield return(new TestCaseData("Array(obj) - different array - different content (value)", arraySpecObject3, arraySpecObject2, false));

            yield return(new TestCaseData("Array(obj) - different array - one is null", arraySpecObject3, arraySpecObjectnull, false));
        }
예제 #8
0
 private static ArrayJsonSpec ToJson(ArraySpec arraySpec, string layoutFile, string meshFile, string relativeDir)
 {
     return new ArrayJsonSpec() {
         BypassDiode = ToJson(arraySpec.BypassDiodeSpec),
         Cell = ToJson(arraySpec.CellSpec),
         EncapsulationLoss = arraySpec.EncapsulationLoss,
         LayoutBounds = ToJson(arraySpec.LayoutBounds),
         LayoutFilename = GetRelative(relativeDir, layoutFile),
         MeshFilename = GetRelative(relativeDir, meshFile)
     };
 }
예제 #9
0
        /// <summary>
        /// Digraph of bypass diodes for calculation.
        /// </summary>
        /*private class BypassNode {
            public int minCell, maxCell;
            public List<BypassNode> childs = new List<BypassNode>();
        }
        private static BypassNode GetRoot(ArraySpec.CellString cellStr) {
            BypassNode root = new BypassNode();
            root.minCell = 0;
            root.maxCell = cellStr.Cells.Count;
            foreach (ArraySpec.BypassDiode diode in cellStr.BypassDiodes) {
                BypassNode node = root;
                while(true){
                    bool found = false;
                    foreach (BypassNode child in node.childs) {
                        if (diode.CellIxs.First >= node.minCell &&
                            diode.CellIxs.Second <= node.maxCell) {
                            node = child;
                            found = true;
                            break;
                        }
                    }
                    if (!found) break;
                }

                BypassNode newNode = new BypassNode();
                newNode.minCell = diode.CellIxs.First;
                newNode.maxCell = diode.CellIxs.Second;
                node.childs.Add(newNode);
            }
            return root;
        }*/
        public static IVTrace CalcStringIV(ArraySpec.CellString cellStr, IVTrace[] cellTraces, DiodeSpec bypassSpec)
        {
            Debug.Assert(cellTraces.Length != 0);
            Debug.Assert(cellTraces.Length == cellStr.Cells.Count);
            int ncells = cellTraces.Length;
            double strIsc = cellTraces[0].Isc;
            for (int i = 0; i < cellTraces.Length; i++) {
                strIsc = Math.Max(strIsc, cellTraces[i].Isc);
            }

            // which nodes connect to which others via bypass diode?
            // there's one node between each cell (subtotal ncells-1),
            // plus one at each end of the string, total ncells+1
            List<int>[] links = new List<int>[ncells+1];
            for(int i = 0; i <= ncells; i++){
                links[i] = new List<int>();
            }
            foreach (ArraySpec.BypassDiode diode in cellStr.BypassDiodes) {
                links[diode.CellIxs.Second + 1].Add(diode.CellIxs.First);
            }

            // sweep current this time, compute voltage
            int nsamples = 200;
            int ngoodsamples = nsamples;
            double[] veci = new double[nsamples];
            double[] vecv = new double[nsamples];
            for (int i = 0; i < nsamples; i++) {
                double current = i * strIsc / (nsamples-1);

                // what cells are in bypass?
                double[] nodevs = new double[ncells+1];
                nodevs[0] = 0; // string starts at ground, zero volts
                for (int j = 1; j <= ncells; j++) {
                    // first, voltage assuming no bypass
                    double nodev = nodevs[j - 1];
                    if (current < cellTraces[j - 1].Isc) {
                        nodev += cellTraces[j - 1].InterpV(current);
                    } else {
                        nodev = Double.NegativeInfinity;
                    }
                    // then, can we do better with bypass?
                    foreach (int linkIx in links[j]) {
                        nodev = Math.Max(nodev, nodevs[linkIx] - bypassSpec.VoltageDrop);
                    }
                    nodevs[j] = nodev;
                }
                veci[i] = current;
                vecv[i] = Math.Max(nodevs[ncells], 0);

                // cut off the part of the trace that's invalid (unachievable current)
                if (nodevs[ncells] >= 0) {
                    Debug.Assert(ngoodsamples == nsamples); // should not "bounce"
                } else if(ngoodsamples == nsamples){
                    ngoodsamples = i;
                }
            }

            // calculate summary info such as mppt power
            double vmp = 0, imp = 0;
            for (int i = 0; i < nsamples; i++) {
                if (veci[i] * vecv[i] > vmp * imp) {
                    vmp = vecv[i];
                    imp = veci[i];
                }
            }

            // return a trace. supports lin interp, etc
            IVTrace trace = new IVTrace();
            ngoodsamples = Math.Min(ngoodsamples + 1, nsamples);
            Debug.Assert(ngoodsamples > 0);
            trace.I = new double[ngoodsamples];
            trace.V = new double[ngoodsamples];
            Array.Copy(veci, trace.I, ngoodsamples);
            Array.Copy(vecv, trace.V, ngoodsamples);
            trace.Isc = veci[ngoodsamples - 1];
            trace.Voc = vecv[0];
            trace.Imp = imp;
            trace.Vmp = vmp;
            return trace;
        }
예제 #10
0
        private void SetUniforms(ArraySpec array, double insolation)
        {
            GL.UseProgram(shaderProg);

            // array layout alignment
            GL.Uniform1(uniformX0, array.LayoutBoundsXZ.Left);
            GL.Uniform1(uniformX1, array.LayoutBoundsXZ.Right);
            GL.Uniform1(uniformZ0, array.LayoutBoundsXZ.Top);
            GL.Uniform1(uniformZ1, array.LayoutBoundsXZ.Bottom);

            // array layout texture. shows where each cell is located.
            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, texArray);
            if (cacheSolarCells != array.LayoutTexture) {
                cacheSolarCells = array.LayoutTexture;
                GLUtils.LoadTexture(array.LayoutTexture, TextureUnit.Texture0);
            }
            GL.Uniform1(uniformSolarCells, (float)TextureUnit.Texture0);

            // solar insolation per pixel rendered
            // (since we are rendering orth projection from the sun's pov, this is a constant)
            double arrayDimM = ComputeArrayMaxDimension(array);
            double m2PerPixel = arrayDimM*arrayDimM/COMPUTE_TEX_SIZE/COMPUTE_TEX_SIZE;
            double wattsPerPixel = m2PerPixel * insolation;
            GL.Uniform1(uniformPixelWattsIn, (float)wattsPerPixel);

            Debug.WriteLine("uniforms set.");
        }
예제 #11
0
 /// <summary>
 /// Computes the diameter of the array (ie, the maximum dimension) in meters.
 /// 
 /// Approximates by finding the diagonal length of the bounding box, for simplicity.
 /// </summary>
 private double ComputeArrayMaxDimension(ArraySpec array)
 {
     Quad3 arrayBB = array.Mesh.BoundingBox;
     return (arrayBB.Max - arrayBB.Min).Length;
 }
예제 #12
0
 /// <summary>
 /// Finds the center of the array mesh. Uses the middle of the bounding box, for simplicity.
 /// </summary>
 private Vector3 ComputeArrayCenter(ArraySpec array)
 {
     Quad3 arrayBB = array.Mesh.BoundingBox;
     return (arrayBB.Max + arrayBB.Min) * 0.5f;
 }
예제 #13
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;
        }
예제 #14
0
        public ArraySimulationStepOutput Simulate(ArraySpec array, Vector3 sunDir, 
            double wPerM2Insolation, double wPerM2Indirect, double encapLoss, double cTemp)
        {
            // validate that we're gtg
            if (array == null) throw new ArgumentException("No array specified.");
            if (array.Mesh == null) throw new ArgumentException("No array shape (mesh) loaded.");
            if (array.LayoutTexture == null) throw new ArgumentException("No array layout (texture) loaded.");
            if (wPerM2Insolation < 0) throw new ArgumentException("Invalid (negative) insolation.");
            if (Math.Abs(sunDir.Length - 1.0) > 1e-3) throw new ArgumentException("Sun direction must be a unit vector.");

            ArraySimulationStepOutput output;
            lock (typeof(GL)) {
                DateTime dt1 = DateTime.Now;
                SetUniforms(array, wPerM2Insolation);
                ComputeRender(array, sunDir);
                DebugSaveBuffers();
                output = AnalyzeComputeTex(array, wPerM2Insolation, wPerM2Indirect, encapLoss, cTemp);
                DateTime dt2 = DateTime.Now;

                Debug.WriteLine(string.Format("finished sim step! {0:0.000}s {1:0.0}/{2:0.0}W",
                    (double)(dt2.Ticks - dt1.Ticks) * 0.0000001,
                    output.WattsInsolation, output.WattsOutput));
            }

            return output;
        }
예제 #15
0
 private void AddArray(ArraySpec array)
 {
     if (ArraySpecs == null)
         ArraySpecs = new List<ArraySpec>();
     ArraySpecs.Add(array);
 }