예제 #1
0
        public static IVTrace CalcSweep(CellSpec cell, double insolationW, double tempC)
        {
            double voc = cell.CalcVoc(insolationW, tempC);
            double isc = cell.CalcIsc(insolationW, tempC);
            int n = 100;
            double[] vecv = new double[n + 1];
            for (int i = 0; i <= n; i++) {
                vecv[i] = voc * (double)i / n;
            }
            double[] veci = CalcIV(cell, vecv, insolationW, tempC);
            //Debug.Assert(Math.Abs(veci[0] - isc) < 0.001);
            //Debug.Assert(Math.Abs(veci[n]) < 0.001);
            double pmp = 0.0;
            double imp = 0.0, vmp = 0.0;
            for (int i = 0; i < n; i++) {
                double p = veci[i] * vecv[i];
                if (p > pmp) {
                    pmp = p;
                    vmp = vecv[i];
                    imp = veci[i];
                }
            }

            IVTrace trace = new IVTrace();
            trace.I = veci;
            trace.V = vecv;
            trace.Isc = isc;
            trace.Voc = voc;
            trace.Imp = imp;
            trace.Vmp = vmp;
            return trace;
        }
예제 #2
0
 /// <summary>
 /// Computes an IV curve.
 /// </summary>
 public static double[] CalcIV(CellSpec cell, double[] vecv, double insolationW, double tempC)
 {
     double[] veci = new double[vecv.Length];
     double i0 = cell.CalcI0(insolationW, tempC);
     double isc = cell.CalcIsc(insolationW, tempC);
     double t = tempC + Constants.C_IN_KELVIN;
     double k = Constants.BOLTZMANN_K;
     double q = Constants.ELECTRON_CHARGE_Q;
     double ni = cell.NIdeal;
     double rs = cell.SeriesR;
     double epsilon = 0.000001;
     bool invalid = false;
     for (int i = 0; i < vecv.Length; i++) {
         double v = vecv[i];
         // iterate to convergence
         double iprev = 0.0, icurr = 0.0;
         for (int j = 0; j < 2000; j++) {
             double vdrop = iprev * rs;
             double idark = i0 * (Math.Exp((q * (v + vdrop)) / (ni * k * t)) - 1.0);
             icurr = isc - idark;
             if (Math.Abs(icurr - iprev) < 1e-6) {
                 //Debug.WriteLine("converged in " + j);
                 break;
             }
             iprev = 0.95 * iprev + 0.05 * icurr;
         }
         // check for invalid results (the simulation didn't converge)
         if (icurr < -epsilon || (i > 0 && icurr > veci[i - 1])){
             invalid = true;
         }
         veci[i] = Math.Max(icurr, 0.0);
     }
     if (invalid)
     {
         Debug.WriteLine("Warning: the IV trace didn't converge, returning zero currents");
         return new double[vecv.Length];
     }
     return veci;
 }
예제 #3
0
        private void Recalculate()
        {
            // recalc
            CellSpec spec = new CellSpec();
            UpdateSpec(spec);

            // show sanity checks
            double i0 = spec.CalcI0(wattsIn, tempC);
            double isc = spec.CalcIsc(wattsIn, tempC);
            double voc = spec.CalcVoc(wattsIn, tempC);
            IVTrace sweep = CellSimulator.CalcSweep(spec, wattsIn, tempC);
            labelMaxPower.Text = string.Format(
                "Isc={0:0.000}A Voc={1:0.000}V @{2:0.00}C\n" +
                "Imp={3:0.000}A Vmp={4:0.000}V Pmp={5:0.000}W\n" +
                "Rev. sat. current {6:0.000}A, fill factor {7:0.0}%",
                isc, voc, tempC,
                sweep.Imp, sweep.Vmp, sweep.Pmp,
                i0, sweep.FillFactor * 100.0);

            // show an iv plot
            chartIV.X = sweep.V;
            chartIV.Y = sweep.I;
        }