/// <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; }
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; }