예제 #1
0
        /// <summary>
        /// Calculate excess phase
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="args">Arguments</param>
        public void CalculateExcessPhase(object sender, ExcessPhaseEventArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            double td = _modeltemp.ExcessPhaseFactor;

            if (td.Equals(0))
            {
                StateExcessPhaseCurrentBc.Current = args.ExcessPhaseCurrent;
                return;
            }

            /*
             * weil's approx. for excess phase applied with backward -
             * euler integration
             */
            double cbe = args.ExcessPhaseCurrent;
            double gbe = args.ExcessPhaseConduct;

            double delta     = StateExcessPhaseCurrentBc.Timesteps[0];
            double prevdelta = StateExcessPhaseCurrentBc.Timesteps[1];
            var    arg1      = delta / td;
            var    arg2      = 3 * arg1;

            arg1 = arg2 * arg1;
            var denom = 1 + arg1 + arg2;
            var arg3  = arg1 / denom;

            /* Still need a place for this...
             * if (state.Init == State.InitFlags.InitTransient)
             * {
             *  state.States[1][State + Cexbc] = cbe / qb;
             *  state.States[2][State + Cexbc] = state.States[1][State + Cexbc];
             * } */
            args.CollectorCurrent = (StateExcessPhaseCurrentBc[1] * (1 + delta / prevdelta + arg2)
                                     - StateExcessPhaseCurrentBc[2] * delta / prevdelta) / denom;
            args.ExcessPhaseCurrent           = cbe * arg3;
            args.ExcessPhaseConduct           = gbe * arg3;
            StateExcessPhaseCurrentBc.Current = args.CollectorCurrent + args.ExcessPhaseCurrent / args.BaseCharge;
        }
예제 #2
0
        /// <summary>
        /// Execute behavior
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public override void Load(BaseSimulation simulation)
        {
            if (simulation == null)
            {
                throw new ArgumentNullException(nameof(simulation));
            }

            var    state = simulation.RealState;
            double vbe;
            double vbc;
            double gben;
            double cben;
            double gbcn;
            double cbcn;

            var vt = _bp.Temperature * Circuit.KOverQ;

            // DC model parameters
            var csat = _temp.TempSaturationCurrent * _bp.Area;
            var rbpr = _mbp.MinimumBaseResistance / _bp.Area;
            var rbpi = _mbp.BaseResist / _bp.Area - rbpr;
            var gcpr = _modeltemp.CollectorConduct * _bp.Area;
            var gepr = _modeltemp.EmitterConduct * _bp.Area;
            var oik  = _modeltemp.InverseRollOffForward / _bp.Area;
            var c2   = _temp.TempBeLeakageCurrent * _bp.Area;
            var vte  = _mbp.LeakBeEmissionCoefficient * vt;
            var oikr = _modeltemp.InverseRollOffReverse / _bp.Area;
            var c4   = _temp.TempBcLeakageCurrent * _bp.Area;
            var vtc  = _mbp.LeakBcEmissionCoefficient * vt;
            var xjrb = _mbp.BaseCurrentHalfResist * _bp.Area;

            // Initialization
            if (state.Init == RealState.InitializationStates.InitJunction && state.Domain == RealState.DomainType.Time && state.UseDc && state.UseIc)
            {
                vbe = _mbp.BipolarType * _bp.InitialVoltageBe;
                var vce = _mbp.BipolarType * _bp.InitialVoltageCe;
                vbc = vbe - vce;
            }
            else if (state.Init == RealState.InitializationStates.InitJunction && !_bp.Off)
            {
                vbe = _temp.TempVCritical;
                vbc = 0;
            }
            else if (state.Init == RealState.InitializationStates.InitJunction || state.Init == RealState.InitializationStates.InitFix && _bp.Off)
            {
                vbe = 0;
                vbc = 0;
            }
            else
            {
                // Compute new nonlinear branch voltages
                vbe = _mbp.BipolarType * (state.Solution[BasePrimeNode] - state.Solution[EmitterPrimeNode]);
                vbc = _mbp.BipolarType * (state.Solution[BasePrimeNode] - state.Solution[CollectorPrimeNode]);

                // Limit nonlinear branch voltages
                bool limited = false;
                vbe = Semiconductor.LimitJunction(vbe, VoltageBe, vt, _temp.TempVCritical, ref limited);
                vbc = Semiconductor.LimitJunction(vbc, VoltageBc, vt, _temp.TempVCritical, ref limited);
                if (limited)
                {
                    state.IsConvergent = false;
                }
            }

            // Determine dc current and derivitives
            var vtn = vt * _mbp.EmissionCoefficientForward;

            if (vbe > -5 * vtn)
            {
                var evbe = Math.Exp(vbe / vtn);
                CurrentBe = csat * (evbe - 1) + state.Gmin * vbe;
                CondBe    = csat * evbe / vtn + state.Gmin;
                if (c2.Equals(0)) // Avoid Exp()
                {
                    cben = 0;
                    gben = 0;
                }
                else
                {
                    var evben = Math.Exp(vbe / vte);
                    cben = c2 * (evben - 1);
                    gben = c2 * evben / vte;
                }
            }
            else
            {
                CondBe    = -csat / vbe + state.Gmin;
                CurrentBe = CondBe * vbe;
                gben      = -c2 / vbe;
                cben      = gben * vbe;
            }

            vtn = vt * _mbp.EmissionCoefficientReverse;
            if (vbc > -5 * vtn)
            {
                var evbc = Math.Exp(vbc / vtn);
                CurrentBc = csat * (evbc - 1) + state.Gmin * vbc;
                CondBc    = csat * evbc / vtn + state.Gmin;
                if (c4.Equals(0)) // Avoid Exp()
                {
                    cbcn = 0;
                    gbcn = 0;
                }
                else
                {
                    var evbcn = Math.Exp(vbc / vtc);
                    cbcn = c4 * (evbcn - 1);
                    gbcn = c4 * evbcn / vtc;
                }
            }
            else
            {
                CondBc    = -csat / vbc + state.Gmin;
                CurrentBc = CondBc * vbc;
                gbcn      = -c4 / vbc;
                cbcn      = gbcn * vbc;
            }

            // Determine base charge terms
            var q1 = 1 / (1 - _modeltemp.InverseEarlyVoltForward * vbc - _modeltemp.InverseEarlyVoltReverse * vbe);

            if (oik.Equals(0) && oikr.Equals(0)) // Avoid computations
            {
                BaseCharge = q1;
                Dqbdve     = q1 * BaseCharge * _modeltemp.InverseEarlyVoltReverse;
                Dqbdvc     = q1 * BaseCharge * _modeltemp.InverseEarlyVoltForward;
            }
            else
            {
                var    q2    = oik * CurrentBe + oikr * CurrentBc;
                var    arg   = Math.Max(0, 1 + 4 * q2);
                double sqarg = 1;
                if (!arg.Equals(0)) // Avoid Sqrt()
                {
                    sqarg = Math.Sqrt(arg);
                }
                BaseCharge = q1 * (1 + sqarg) / 2;
                Dqbdve     = q1 * (BaseCharge * _modeltemp.InverseEarlyVoltReverse + oik * CondBe / sqarg);
                Dqbdvc     = q1 * (BaseCharge * _modeltemp.InverseEarlyVoltForward + oikr * CondBc / sqarg);
            }

            // Excess phase calculation
            ExcessPhaseEventArgs ep = new ExcessPhaseEventArgs
            {
                CollectorCurrent   = 0.0,
                ExcessPhaseCurrent = CurrentBe,
                ExcessPhaseConduct = CondBe,
                BaseCharge         = BaseCharge
            };

            ExcessPhaseCalculation?.Invoke(this, ep);
            var cc  = ep.CollectorCurrent;
            var cex = ep.ExcessPhaseCurrent;
            var gex = ep.ExcessPhaseConduct;

            // Determine dc incremental conductances
            cc = cc + (cex - CurrentBc) / BaseCharge - CurrentBc / _temp.TempBetaReverse - cbcn;
            var cb = CurrentBe / _temp.TempBetaForward + cben + CurrentBc / _temp.TempBetaReverse + cbcn;
            var gx = rbpr + rbpi / BaseCharge;

            if (!xjrb.Equals(0)) // Avoid calculations
            {
                var arg1 = Math.Max(cb / xjrb, 1e-9);
                var arg2 = (-1 + Math.Sqrt(1 + 14.59025 * arg1)) / 2.4317 / Math.Sqrt(arg1);
                arg1 = Math.Tan(arg2);
                gx   = rbpr + 3 * rbpi * (arg1 - arg2) / arg2 / arg1 / arg1;
            }
            if (!gx.Equals(0)) // Do not divide by 0
            {
                gx = 1 / gx;
            }
            var gpi = CondBe / _temp.TempBetaForward + gben;
            var gmu = CondBc / _temp.TempBetaReverse + gbcn;
            var go  = (CondBc + (cex - CurrentBc) * Dqbdvc / BaseCharge) / BaseCharge;
            var gm  = (gex - (cex - CurrentBc) * Dqbdve / BaseCharge) / BaseCharge - go;

            VoltageBe         = vbe;
            VoltageBc         = vbc;
            CollectorCurrent  = cc;
            BaseCurrent       = cb;
            ConductancePi     = gpi;
            ConductanceMu     = gmu;
            Transconductance  = gm;
            OutputConductance = go;
            ConductanceX      = gx;

            // Load current excitation vector
            var ceqbe = _mbp.BipolarType * (cc + cb - vbe * (gm + go + gpi) + vbc * go);
            var ceqbc = _mbp.BipolarType * (-cc + vbe * (gm + go) - vbc * (gmu + go));

            CollectorPrimePtr.Value += ceqbc;
            BasePrimePtr.Value      += -ceqbe - ceqbc;
            EmitterPrimePtr.Value   += ceqbe;

            // Load y matrix
            CollectorCollectorPtr.Value           += gcpr;
            BaseBasePtr.Value                     += gx;
            EmitterEmitterPtr.Value               += gepr;
            CollectorPrimeCollectorPrimePtr.Value += gmu + go + gcpr;
            BasePrimeBasePrimePtr.Value           += gx + gpi + gmu;
            EmitterPrimeEmitterPrimePtr.Value     += gpi + gepr + gm + go;
            CollectorCollectorPrimePtr.Value      += -gcpr;
            BaseBasePrimePtr.Value                += -gx;
            EmitterEmitterPrimePtr.Value          += -gepr;
            CollectorPrimeCollectorPtr.Value      += -gcpr;
            CollectorPrimeBasePrimePtr.Value      += -gmu + gm;
            CollectorPrimeEmitterPrimePtr.Value   += -gm - go;
            BasePrimeBasePtr.Value                += -gx;
            BasePrimeCollectorPrimePtr.Value      += -gmu;
            BasePrimeEmitterPrimePtr.Value        += -gpi;
            EmitterPrimeEmitterPtr.Value          += -gepr;
            EmitterPrimeCollectorPrimePtr.Value   += -go;
            EmitterPrimeBasePrimePtr.Value        += -gpi - gm;
        }