/// <summary> /// Truncate the timestep /// </summary> /// <returns>The timestep that satisfies the LTE</returns> public override double Truncate() { double timetmp = StateChargeBe.LocalTruncationError(); timetmp = Math.Min(timetmp, StateChargeBc.LocalTruncationError()); timetmp = Math.Min(timetmp, StateChargeCs.LocalTruncationError()); return(timetmp); }
/// <summary> /// Transient behavior /// </summary> /// <param name="simulation">Time-based simulation</param> public override void Transient(TimeSimulation simulation) { if (simulation == null) { throw new ArgumentNullException(nameof(simulation)); } var state = simulation.RealState; double arg; double sarg, f1, f2, f3; double cbe = _load.CurrentBe; double cbc = _load.CurrentBc; double gbe = _load.CondBe; double gbc = _load.CondBc; double qb = _load.BaseCharge; double geqcb = 0; double gpi = 0.0; double gmu = 0.0; double cb = 0.0; double cc = 0.0; double vbe = _load.VoltageBe; double vbc = _load.VoltageBc; double vbx = _mbp.BipolarType * (state.Solution[_baseNode] - state.Solution[_colPrimeNode]); double vcs = _mbp.BipolarType * (state.Solution[_substrateNode] - state.Solution[_colPrimeNode]); // Charge storage elements double tf = _mbp.TransitTimeForward; double tr = _mbp.TransitTimeReverse; var czbe = _temp.TempBeCap * _bp.Area; var pe = _temp.TempBePotential; double xme = _mbp.JunctionExpBe; double cdis = _mbp.BaseFractionBcCap; var ctot = _temp.TempBcCap * _bp.Area; var czbc = ctot * cdis; var czbx = ctot - czbc; var pc = _temp.TempBcPotential; double xmc = _mbp.JunctionExpBc; var fcpe = _temp.TempDepletionCap; var czcs = _mbp.CapCs * _bp.Area; double ps = _mbp.PotentialSubstrate; double xms = _mbp.ExponentialSubstrate; double xtf = _mbp.TransitTimeBiasCoefficientForward; var ovtf = _modeltemp.TransitTimeVoltageBcFactor; var xjtf = _mbp.TransitTimeHighCurrentForward * _bp.Area; if (!tf.Equals(0) && vbe > 0) // Avoid computations { double argtf = 0; double arg2 = 0; double arg3 = 0; if (!xtf.Equals(0)) // Avoid computations { argtf = xtf; if (!ovtf.Equals(0)) // Avoid expensive Exp() { argtf = argtf * Math.Exp(vbc * ovtf); } arg2 = argtf; if (!xjtf.Equals(0)) // Avoid computations { var tmp = cbe / (cbe + xjtf); argtf = argtf * tmp * tmp; arg2 = argtf * (3 - tmp - tmp); } arg3 = cbe * argtf * ovtf; } cbe = cbe * (1 + argtf) / qb; gbe = (gbe * (1 + arg2) - cbe * _load.Dqbdve) / qb; geqcb = tf * (arg3 - cbe * _load.Dqbdvc) / qb; } if (vbe < fcpe) { arg = 1 - vbe / pe; sarg = Math.Exp(-xme * Math.Log(arg)); StateChargeBe.Current = tf * cbe + pe * czbe * (1 - arg * sarg) / (1 - xme); CapBe = tf * gbe + czbe * sarg; } else { f1 = _temp.TempFactor1; f2 = _modeltemp.F2; f3 = _modeltemp.F3; var czbef2 = czbe / f2; StateChargeBe.Current = tf * cbe + czbe * f1 + czbef2 * (f3 * (vbe - fcpe) + xme / (pe + pe) * (vbe * vbe - fcpe * fcpe)); CapBe = tf * gbe + czbef2 * (f3 + xme * vbe / pe); } var fcpc = _temp.TempFactor4; f1 = _temp.TempFactor5; f2 = _modeltemp.F6; f3 = _modeltemp.F7; if (vbc < fcpc) { arg = 1 - vbc / pc; sarg = Math.Exp(-xmc * Math.Log(arg)); StateChargeBc.Current = tr * cbc + pc * czbc * (1 - arg * sarg) / (1 - xmc); CapBc = tr * gbc + czbc * sarg; } else { var czbcf2 = czbc / f2; StateChargeBc.Current = tr * cbc + czbc * f1 + czbcf2 * (f3 * (vbc - fcpc) + xmc / (pc + pc) * (vbc * vbc - fcpc * fcpc)); CapBc = tr * gbc + czbcf2 * (f3 + xmc * vbc / pc); } if (vbx < fcpc) { arg = 1 - vbx / pc; sarg = Math.Exp(-xmc * Math.Log(arg)); StateChargeBx.Current = pc * czbx * (1 - arg * sarg) / (1 - xmc); CapBx = czbx * sarg; } else { var czbxf2 = czbx / f2; StateChargeBx.Current = czbx * f1 + czbxf2 * (f3 * (vbx - fcpc) + xmc / (pc + pc) * (vbx * vbx - fcpc * fcpc)); CapBx = czbxf2 * (f3 + xmc * vbx / pc); } if (vcs < 0) { arg = 1 - vcs / ps; sarg = Math.Exp(-xms * Math.Log(arg)); StateChargeCs.Current = ps * czcs * (1 - arg * sarg) / (1 - xms); CapCs = czcs * sarg; } else { StateChargeCs.Current = vcs * czcs * (1 + xms * vcs / (2 * ps)); CapCs = czcs * (1 + xms * vcs / ps); } StateChargeBe.Integrate(); geqcb = StateChargeBe.Jacobian(geqcb); // Multiplies geqcb with method.Slope (ag[0]) gpi += StateChargeBe.Jacobian(CapBe); cb += StateChargeBe.Derivative; StateChargeBc.Integrate(); gmu += StateChargeBc.Jacobian(CapBc); cb += StateChargeBc.Derivative; cc -= StateChargeBc.Derivative; // Charge storage for c-s and b-x junctions StateChargeCs.Integrate(); double gccs = StateChargeCs.Jacobian(CapCs); StateChargeBx.Integrate(); double geqbx = StateChargeBx.Jacobian(CapBx); // Load current excitation vector double ceqcs = _mbp.BipolarType * (StateChargeCs.Derivative - vcs * gccs); double ceqbx = _mbp.BipolarType * (StateChargeBx.Derivative - vbx * geqbx); double ceqbe = _mbp.BipolarType * (cc + cb - vbe * gpi + vbc * -geqcb); double ceqbc = _mbp.BipolarType * (-cc + -vbc * gmu); // Load Rhs-vector BasePtr.Value += -ceqbx; CollectorPrimePtr.Value += ceqcs + ceqbx + ceqbc; BasePrimePtr.Value += -ceqbe - ceqbc; EmitterPrimePtr.Value += ceqbe; SubstratePtr.Value += -ceqcs; // Load Y-matrix BaseBasePtr.Value += geqbx; CollectorPrimeCollectorPrimePtr.Value += gmu + gccs + geqbx; BasePrimeBasePrimePtr.Value += gpi + gmu + geqcb; EmitterPrimeEmitterPrimePtr.Value += gpi; CollectorPrimeBasePrimePtr.Value += -gmu; BasePrimeCollectorPrimePtr.Value += -gmu - geqcb; BasePrimeEmitterPrimePtr.Value += -gpi; EmitterPrimeCollectorPrimePtr.Value += geqcb; EmitterPrimeBasePrimePtr.Value += -gpi - geqcb; SubstrateSubstratePtr.Value += gccs; CollectorPrimeSubstratePtr.Value += -gccs; SubstrateCollectorPrimePtr.Value += -gccs; BaseCollectorPrimePtr.Value += -geqbx; CollectorPrimeBasePtr.Value += -geqbx; }