예제 #1
0
        /// <summary>
        /// Initialize the device based on the current iteration state.
        /// </summary>
        protected void Initialize(out double vd, out bool check)
        {
            check = false;
            if (_iteration.Mode == IterationModes.Junction)
            {
                vd = Parameters.Off ? 0.0 : TempVCritical;
            }
            else if (_iteration.Mode == IterationModes.Fix && Parameters.Off)
            {
                vd = 0.0;
            }
            else
            {
                // Get voltage over the diodes (without series resistance).
                vd = (Variables.PosPrime.Value - Variables.Negative.Value) / Parameters.SeriesMultiplier;

                // Limit new junction voltage.
                if (ModelParameters.BreakdownVoltage.Given && vd < Math.Min(0, -TempBreakdownVoltage + 10 * Vte))
                {
                    var vdtemp = -(vd + TempBreakdownVoltage);
                    vdtemp = Semiconductor.LimitJunction(vdtemp, -(LocalVoltage + TempBreakdownVoltage), Vte, TempVCritical, ref check);
                    vd     = -(vdtemp + TempBreakdownVoltage);
                }
                else
                {
                    vd = Semiconductor.LimitJunction(vd, LocalVoltage, Vte, TempVCritical, ref check);
                }
            }
        }
        private static Structure CreateSiO2TestStructure()
        {
            var topMetal = new Metal(Length.FromNanometers(4));

            topMetal.SetWorkFunction(Energy.FromElectronVolts(4.45));

            var oxide = new Dielectric(Length.FromNanometers(2));

            oxide.DielectricConstant = 3.9;
            oxide.BandGap            = Energy.FromElectronVolts(8.9);
            oxide.ElectronAffinity   = Energy.FromElectronVolts(0.95);

            var semiconductor = new Semiconductor();

            semiconductor.BandGap                       = Energy.FromElectronVolts(1.1252);
            semiconductor.ElectronAffinity              = Energy.FromElectronVolts(4.05);
            semiconductor.DielectricConstant            = 11.7;
            semiconductor.IntrinsicCarrierConcentration = Concentration.FromPerCubicCentimeter(1.41E10);
            semiconductor.DopingType                    = DopingType.N;
            semiconductor.DopantConcentration           = Concentration.FromPerCubicCentimeter(1E18);

            var structure = new Structure();

            structure.Temperature = new Temperature(300);
            structure.AddLayer(semiconductor);
            structure.AddLayer(oxide);
            structure.AddLayer(topMetal);

            return(structure);
        }
예제 #3
0
        /// <summary>
        /// Initialize the device based on the current iteration state.
        /// </summary>
        protected void Initialize(out double vd, out bool check)
        {
            var state = State;

            check = false;
            if (state.Init == InitializationModes.Junction)
            {
                vd = BaseParameters.Off ? 0.0 : TempVCritical;
            }
            else if (state.Init == InitializationModes.Fix && BaseParameters.Off)
            {
                vd = 0.0;
            }
            else
            {
                // Get voltage over the diode (without series resistance)
                vd = state.Solution[PosPrimeNode] - state.Solution[NegNode];

                // limit new junction voltage
                if (ModelParameters.BreakdownVoltage.Given && vd < Math.Min(0, -TempBreakdownVoltage + 10 * Vte))
                {
                    var vdtemp = -(vd + TempBreakdownVoltage);
                    vdtemp = Semiconductor.LimitJunction(vdtemp, -(Voltage + TempBreakdownVoltage), Vte, TempVCritical, ref check);
                    vd     = -(vdtemp + TempBreakdownVoltage);
                }
                else
                {
                    vd = Semiconductor.LimitJunction(vd, Voltage, Vte, TempVCritical, ref check);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Initializes the voltages for the current iteration.
        /// </summary>
        /// <param name="vbe">The base-emitter voltage.</param>
        /// <param name="vbc">The base-collector voltage.</param>
        protected virtual void Initialize(out double vbe, out double vbc)
        {
            var state = BiasingState;

            // Initialization
            if (Iteration.Mode == IterationModes.Junction && !Parameters.Off)
            {
                vbe = TempVCritical;
                vbc = 0;
            }
            else if (Iteration.Mode == IterationModes.Junction || Iteration.Mode == IterationModes.Fix && Parameters.Off)
            {
                vbe = 0;
                vbc = 0;
            }
            else
            {
                // Compute new nonlinear branch voltages
                vbe = ModelParameters.BipolarType * (state.Solution[_basePrimeNode] - state.Solution[_emitterPrimeNode]);
                vbc = ModelParameters.BipolarType * (state.Solution[_basePrimeNode] - state.Solution[_collectorPrimeNode]);

                // Limit nonlinear branch voltages
                var limited = false;
                vbe = Semiconductor.LimitJunction(vbe, VoltageBe, Vt, TempVCritical, ref limited);
                vbc = Semiconductor.LimitJunction(vbc, VoltageBc, Vt, TempVCritical, ref limited);
                if (limited)
                {
                    Iteration.IsConvergent = false;
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Initializes the voltages to be used for calculating the current iteration.
        /// </summary>
        /// <param name="simulation">The simulation.</param>
        /// <param name="vgs">The VGS.</param>
        /// <param name="vds">The VDS.</param>
        /// <param name="vbs">The VBS.</param>
        /// <param name="check">If set to <c>true</c>, the current voltage was limited and another iteration should be calculated.</param>
        protected void Initialize(BaseSimulation simulation,
                                  out double vgs, out double vds, out double vbs, out bool check)
        {
            var state = simulation.RealState;

            check = true;

            if (state.Init == InitializationModes.Float || (!state.UseDc && simulation is TimeSimulation tsim && tsim.Method.BaseTime.Equals(0.0)) ||
                state.Init == InitializationModes.Fix && !BaseParameters.Off)
            {
                // General iteration
                vbs = ModelParameters.MosfetType * (state.Solution[BulkNode] - state.Solution[SourceNodePrime]);
                vgs = ModelParameters.MosfetType * (state.Solution[GateNode] - state.Solution[SourceNodePrime]);
                vds = ModelParameters.MosfetType * (state.Solution[DrainNodePrime] - state.Solution[SourceNodePrime]);

                // now some common crunching for some more useful quantities
                var vbd  = vbs - vds;
                var vgd  = vgs - vds;
                var vgdo = VoltageGs - VoltageDs;
                var von  = ModelParameters.MosfetType * Von;

                /*
                 * limiting
                 * we want to keep device voltages from changing
                 * so fast that the exponentials churn out overflows
                 * and similar rudeness
                 */
                // NOTE: Spice 3f5 does not write out Vgs during DC analysis, so DEVfetlim may give different results in Spice 3f5
                if (VoltageDs >= 0)
                {
                    vgs = Transistor.LimitFet(vgs, VoltageGs, von);
                    vds = vgs - vgd;
                    vds = Transistor.LimitVds(vds, VoltageDs);
                }
                else
                {
                    vgd = Transistor.LimitFet(vgd, vgdo, von);
                    vds = vgs - vgd;
                    vds = -Transistor.LimitVds(-vds, -VoltageDs);
                    vgs = vgd + vds;
                }

                check = false;
                if (vds >= 0)
                {
                    vbs = Semiconductor.LimitJunction(vbs, VoltageBs, Vt, SourceVCritical, ref check);
                }
                else
                {
                    vbd = Semiconductor.LimitJunction(vbd, VoltageBd, Vt, DrainVCritical, ref check);
                    vbs = vbd + vds;
                }
            }
        private static Semiconductor CreateTestSemiconductor()
        {
            var semiconductor = new Semiconductor();

            semiconductor.BandGap                       = Energy.FromElectronVolts(1.1252);
            semiconductor.ElectronAffinity              = Energy.FromElectronVolts(4.05);
            semiconductor.DielectricConstant            = 11.7;
            semiconductor.IntrinsicCarrierConcentration = Concentration.FromPerCubicCentimeter(1.41E10);
            semiconductor.DopingType                    = DopingType.N;
            semiconductor.DopantConcentration           = Concentration.FromPerCubicCentimeter(1E18);

            return(semiconductor);
        }
        public void TestStructureWithOnlySemiconductorIsInvalid()
        {
            var semiconductor = new Semiconductor();

            semiconductor.BandGap                       = Energy.FromElectronVolts(1.125);
            semiconductor.ElectronAffinity              = Energy.FromElectronVolts(4.05);
            semiconductor.DielectricConstant            = 11.7;
            semiconductor.IntrinsicCarrierConcentration = Concentration.FromPerCubicCentimeter(1.41E10);
            semiconductor.DopingType                    = DopingType.N;
            semiconductor.DopantConcentration           = Concentration.FromPerCubicCentimeter(1E18);

            var structure = new Structure();

            structure.AddLayer(semiconductor);

            Assert.That(!structure.IsValid);
        }
        public void TestStructureWithoutDielectricIsInvalid()
        {
            var topMetal = new Metal(Length.FromNanometers(10));

            topMetal.SetWorkFunction(Energy.FromElectronVolts(4.9));

            var semiconductor = new Semiconductor();

            semiconductor.BandGap                       = Energy.FromElectronVolts(1.125);
            semiconductor.ElectronAffinity              = Energy.FromElectronVolts(4.05);
            semiconductor.DielectricConstant            = 11.7;
            semiconductor.IntrinsicCarrierConcentration = Concentration.FromPerCubicCentimeter(1.41E10);
            semiconductor.DopingType                    = DopingType.N;
            semiconductor.DopantConcentration           = Concentration.FromPerCubicCentimeter(1E18);

            var structure = new Structure();

            structure.AddLayer(semiconductor);
            structure.AddLayer(topMetal);

            Assert.That(!structure.IsValid);
        }
예제 #9
0
        /// <summary>
        /// Initializes the voltages for the current iteration.
        /// </summary>
        /// <param name="simulation">The simulation.</param>
        /// <param name="vgs">The VGS.</param>
        /// <param name="vgd">The VGD.</param>
        /// <param name="check">if set to <c>true</c> [check].</param>
        protected void Initialize(BaseSimulation simulation, out double vgs, out double vgd, out bool check)
        {
            simulation.ThrowIfNull(nameof(simulation));
            var state = simulation.RealState;

            // Initialization
            check = true;
            if (state.Init == InitializationModes.Junction && simulation is TimeSimulation && state.UseDc && state.UseIc)
            {
                var vds = ModelParameters.JFETType * BaseParameters.InitialVds;
                vgs = ModelParameters.JFETType * BaseParameters.InitialVgs;
                vgd = vgs - vds;
            }
            else if (state.Init == InitializationModes.Junction && !BaseParameters.Off)
            {
                vgs = -1;
                vgd = -1;
            }
            else if (state.Init == InitializationModes.Junction || state.Init == InitializationModes.Fix && BaseParameters.Off)
            {
                vgs = 0;
                vgd = 0;
            }
            else
            {
                // Compute new nonlinear branch voltages
                vgs = ModelParameters.JFETType * (state.Solution[GateNode] - state.Solution[SourcePrimeNode]);
                vgd = ModelParameters.JFETType * (state.Solution[GateNode] - state.Solution[DrainPrimeNode]);

                // Limit nonlinear branch voltages
                check = false;
                vgs   = Semiconductor.LimitJunction(vgs, Vgs,
                                                    BaseParameters.Temperature * Constants.KOverQ, Vcrit, ref check);
                vgd = Semiconductor.LimitJunction(vgd, Vgd,
                                                  BaseParameters.Temperature * Constants.KOverQ, Vcrit, ref check);
                vgs = Transistor.LimitFet(vgs, Vgs, ModelParameters.Threshold);
                vgd = Transistor.LimitFet(vgd, Vgd, ModelParameters.Threshold);
            }
        }
예제 #10
0
        /// <summary>
        /// Initializes the voltages for the current iteration.
        /// </summary>
        /// <param name="vgs">The gate-source voltage.</param>
        /// <param name="vgd">The gate-drain voltage.</param>
        /// <param name="check">If set to <c>true</c>, the voltages were limited to avoid blowing up of the currents.</param>
        protected void Initialize(out double vgs, out double vgd, out bool check)
        {
            var state = BiasingState;

            // Initialization
            check = true;
            if (_iteration.Mode == IterationModes.Junction && _method != null && (_time != null && _time.UseDc && _time.UseIc))
            {
                var vds = ModelParameters.JFETType * Parameters.InitialVds;
                vgs = ModelParameters.JFETType * Parameters.InitialVgs;
                vgd = vgs - vds;
            }
            else if (_iteration.Mode == IterationModes.Junction && !Parameters.Off)
            {
                vgs = -1;
                vgd = -1;
            }
            else if (_iteration.Mode == IterationModes.Junction || _iteration.Mode == IterationModes.Fix && Parameters.Off)
            {
                vgs = 0;
                vgd = 0;
            }
            else
            {
                // Compute new nonlinear branch voltages
                vgs = ModelParameters.JFETType * (state.Solution[_gateNode] - state.Solution[_sourcePrimeNode]);
                vgd = ModelParameters.JFETType * (state.Solution[_gateNode] - state.Solution[_drainPrimeNode]);

                // Limit nonlinear branch voltages
                check = false;
                vgs   = Semiconductor.LimitJunction(vgs, Vgs,
                                                    Parameters.Temperature * Constants.KOverQ, Vcrit, ref check);
                vgd = Semiconductor.LimitJunction(vgd, Vgd,
                                                  Parameters.Temperature * Constants.KOverQ, Vcrit, ref check);
                vgs = Transistor.LimitFet(vgs, Vgs, ModelParameters.Threshold);
                vgd = Transistor.LimitFet(vgd, Vgd, ModelParameters.Threshold);
            }
        }
예제 #11
0
        /// <summary>
        /// Initializes the voltages for the current iteration.
        /// </summary>
        /// <param name="vbe">The VBE.</param>
        /// <param name="vbc">The VBC.</param>
        protected void Initialize(out double vbe, out double vbc)
        {
            var state = State;

            // Initialization
            if (state.Init == InitializationModes.Junction && (Simulation is TimeSimulation) && state.UseDc && state.UseIc)
            {
                vbe = ModelParameters.BipolarType * BaseParameters.InitialVoltageBe;
                var vce = ModelParameters.BipolarType * BaseParameters.InitialVoltageCe;
                vbc = vbe - vce;
            }
            else if (state.Init == InitializationModes.Junction && !BaseParameters.Off)
            {
                vbe = TempVCritical;
                vbc = 0;
            }
            else if (state.Init == InitializationModes.Junction || state.Init == InitializationModes.Fix && BaseParameters.Off)
            {
                vbe = 0;
                vbc = 0;
            }
            else
            {
                // Compute new nonlinear branch voltages
                vbe = ModelParameters.BipolarType * (state.Solution[BasePrimeNode] - state.Solution[EmitterPrimeNode]);
                vbc = ModelParameters.BipolarType * (state.Solution[BasePrimeNode] - state.Solution[CollectorPrimeNode]);

                // Limit nonlinear branch voltages
                var limited = false;
                vbe = Semiconductor.LimitJunction(vbe, VoltageBe, Vt, TempVCritical, ref limited);
                vbc = Semiconductor.LimitJunction(vbc, VoltageBc, Vt, TempVCritical, ref limited);
                if (limited)
                {
                    state.IsConvergent = false;
                }
            }
        }
예제 #12
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;
        }
예제 #13
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 vd;
            double cd, gd;

            /*
             * this routine loads diodes for dc and transient analyses.
             */
            var csat = _temp.TempSaturationCurrent * _bp.Area;
            var gspr = _modeltemp.Conductance * _bp.Area;
            var vt   = Circuit.KOverQ * _bp.Temperature;
            var vte  = _mbp.EmissionCoefficient * vt;

            // Initialization
            var check = false;

            if (state.Init == InitializationModes.Junction)
            {
                vd = _bp.Off ? 0.0 : _temp.TempVCritical;
            }
            else if (state.Init == InitializationModes.Fix && _bp.Off)
            {
                vd = 0.0;
            }
            else
            {
                // Get voltage over the diode (without series resistance)
                vd = state.Solution[PosPrimeNode] - state.Solution[_negNode];

                // limit new junction voltage
                if (_mbp.BreakdownVoltage.Given && vd < Math.Min(0, -_temp.TempBreakdownVoltage + 10 * vte))
                {
                    var vdtemp = -(vd + _temp.TempBreakdownVoltage);
                    vdtemp = Semiconductor.LimitJunction(vdtemp, -(InternalVoltage + _temp.TempBreakdownVoltage), vte, _temp.TempVCritical, ref check);
                    vd     = -(vdtemp + _temp.TempBreakdownVoltage);
                }
                else
                {
                    vd = Semiconductor.LimitJunction(vd, InternalVoltage, vte, _temp.TempVCritical, ref check);
                }
            }

            // compute dc current and derivatives
            if (vd >= -3 * vte)
            {
                // Forward bias
                var evd = Math.Exp(vd / vte);
                cd = csat * (evd - 1) + _baseConfig.Gmin * vd;
                gd = csat * evd / vte + _baseConfig.Gmin;
            }
            else if (!_mbp.BreakdownVoltage.Given || vd >= -_temp.TempBreakdownVoltage)
            {
                // Reverse bias
                var arg = 3 * vte / (vd * Math.E);
                arg = arg * arg * arg;
                cd  = -csat * (1 + arg) + _baseConfig.Gmin * vd;
                gd  = csat * 3 * arg / vd + _baseConfig.Gmin;
            }
            else
            {
                // Reverse breakdown
                var evrev = Math.Exp(-(_temp.TempBreakdownVoltage + vd) / vte);
                cd = -csat * evrev + _baseConfig.Gmin * vd;
                gd = csat * evrev / vte + _baseConfig.Gmin;
            }

            // Check convergence
            if (state.Init != InitializationModes.Fix || !_bp.Off)
            {
                if (check)
                {
                    state.IsConvergent = false;
                }
            }

            // Store for next time
            InternalVoltage = vd;
            Current         = cd;
            Conduct         = gd;

            // Load Rhs vector
            var cdeq = cd - gd * vd;

            NegPtr.Value      += cdeq;
            PosPrimePtr.Value -= cdeq;

            // Load Y-matrix
            PosPosPtr.Value           += gspr;
            NegNegPtr.Value           += gd;
            PosPrimePosPrimePtr.Value += gd + gspr;
            PosPosPrimePtr.Value      -= gspr;
            PosPrimePosPtr.Value      -= gspr;
            NegPosPrimePtr.Value      -= gd;
            PosPrimeNegPtr.Value      -= gd;
        }
예제 #14
0
        /// <summary>
        /// Load the diode
        /// </summary>
        /// <param name="ckt"></param>
        public override void Load(Circuit ckt)
        {
            double arg, capd, cd, cdeq, cdhat, csat, czero, czof2, delvd, evd, evrev, gd, gspr, sarg,
                   vd, vdtemp, vt, vte;
            bool Check;

            var state  = ckt.State;
            var rstate = state.Real;
            var method = ckt.Method;

            csat = DIOtSatCur * DIOarea;
            gspr = Model.DIOconductance * DIOarea;
            vt   = Circuit.CONSTKoverQ * DIOtemp;
            vte  = Model.DIOemissionCoeff * vt;

            // initialization
            Check = true;
            if (state.UseSmallSignal)
            {
                vd = state.States[0][DIOstate + DIOvoltage];
            }
            else if (method != null && method.SavedTime == 0.0)
            {
                vd = state.States[1][DIOstate + DIOvoltage];
            }
            else if ((state.Init == CircuitState.InitFlags.InitJct) && (state.Domain == CircuitState.DomainTypes.Time && state.UseDC && state.UseIC))
            {
                vd = DIOinitCond;
            }
            else if (state.Init == CircuitState.InitFlags.InitJct && DIOoff)
            {
                vd = 0.0;
            }
            else if (state.Init == CircuitState.InitFlags.InitJct)
            {
                vd = DIOtVcrit;
            }
            else if (state.Init == CircuitState.InitFlags.InitFix && DIOoff)
            {
                vd = 0.0;
            }
            else
            {
                // Default initialization: use the previous iteration
                vd    = rstate.OldSolution[DIOposPrimeNode] - rstate.OldSolution[DIOnegNode];
                delvd = vd - state.States[0][DIOstate + DIOvoltage];
                cdhat = state.States[0][DIOstate + DIOcurrent] + state.States[0][DIOstate + DIOconduct] * delvd;

                // limit new junction voltage
                if ((Model.DIObreakdownVoltage.Given) && (vd < Math.Min(0, -DIOtBrkdwnV + 10 * vte)))
                {
                    vdtemp = -(vd + DIOtBrkdwnV);
                    vdtemp = Semiconductor.pnjlim(vdtemp, -(state.States[0][DIOstate + DIOvoltage] + DIOtBrkdwnV), vte, DIOtVcrit, ref Check);
                    vd     = -(vdtemp + DIOtBrkdwnV);
                }
                else
                {
                    vd = Semiconductor.pnjlim(vd, state.States[0][DIOstate + DIOvoltage], vte, DIOtVcrit, ref Check);
                }
            }

            // compute dc current and derivatives
            if (vd >= -3 * vte)
            {
                evd = Math.Exp(vd / vte);
                cd  = csat * (evd - 1) + state.Gmin * vd;
                gd  = csat * evd / vte + state.Gmin;
            }
            else if ((DIOtBrkdwnV == 0.0) || vd >= -DIOtBrkdwnV)
            {
                arg = 3 * vte / (vd * Circuit.CONSTE);
                arg = arg * arg * arg;
                cd  = -csat * (1 + arg) + state.Gmin * vd;
                gd  = csat * 3 * arg / vd + state.Gmin;
            }
            else
            {
                evrev = Math.Exp(-(DIOtBrkdwnV + vd) / vte);
                cd    = -csat * evrev + state.Gmin * vd;
                gd    = csat * evrev / vte + state.Gmin;
            }

            // Calculate the charge of the junction capacitance if we're going to need it
            if (method != null || state.UseSmallSignal || state.UseIC)
            {
                // Charge storage elements and junction capacitance
                czero = DIOtJctCap * DIOarea;
                if (vd < DIOtDepCap)
                {
                    arg  = 1 - vd / Model.DIOjunctionPot;
                    sarg = Math.Exp(-Model.DIOgradingCoeff * Math.Log(arg));
                    state.States[0][DIOstate + DIOcapCharge] = Model.DIOtransitTime * cd + Model.DIOjunctionPot * czero * (1 - arg * sarg) / (1 - Model.DIOgradingCoeff);
                    capd = Model.DIOtransitTime * gd + czero * sarg;
                }
                else
                {
                    czof2 = czero / Model.DIOf2;
                    state.States[0][DIOstate + DIOcapCharge] = Model.DIOtransitTime * cd + czero * DIOtF1 + czof2 * (Model.DIOf3 * (vd - DIOtDepCap) +
                                                                                                                     (Model.DIOgradingCoeff / (Model.DIOjunctionPot + Model.DIOjunctionPot)) * (vd * vd - DIOtDepCap * DIOtDepCap));
                    capd = Model.DIOtransitTime * gd + czof2 * (Model.DIOf3 + Model.DIOgradingCoeff * vd / Model.DIOjunctionPot);
                }
                DIOcap = capd;

                // Store small-signal parameters
                if (state.UseSmallSignal)
                {
                    state.States[0][DIOstate + DIOcapCurrent] = capd;
                    return;
                }

                if (method != null && method.SavedTime == 0.0)
                {
                    state.CopyDC(DIOstate + DIOcapCharge);
                }

                // Time-domain analysis
                if (method != null)
                {
                    var result = method.Integrate(state, DIOstate + DIOcapCharge, capd);
                    gd = gd + result.Geq;
                    cd = cd + state.States[0][DIOstate + DIOcapCurrent];
                }
            }

            // check convergence
            if ((state.Init != CircuitState.InitFlags.InitFix) || !DIOoff)
            {
                if (Check)
                {
                    state.IsCon = false;
                }
            }

            state.States[0][DIOstate + DIOvoltage] = vd;
            state.States[0][DIOstate + DIOcurrent] = cd;
            state.States[0][DIOstate + DIOconduct] = gd;

            // load current vector
            cdeq = cd - gd * vd;
            rstate.Rhs[DIOnegNode]      += cdeq;
            rstate.Rhs[DIOposPrimeNode] -= cdeq;

            // load matrix
            rstate.Matrix[DIOposNode, DIOposNode]           += gspr;
            rstate.Matrix[DIOnegNode, DIOnegNode]           += gd;
            rstate.Matrix[DIOposPrimeNode, DIOposPrimeNode] += (gd + gspr);
            rstate.Matrix[DIOposNode, DIOposPrimeNode]      -= gspr;
            rstate.Matrix[DIOnegNode, DIOposPrimeNode]      -= gd;
            rstate.Matrix[DIOposPrimeNode, DIOposNode]      -= gspr;
            rstate.Matrix[DIOposPrimeNode, DIOnegNode]      -= gd;
        }
예제 #15
0
        /// <summary>
        /// Load the bipolar transistor
        /// </summary>
        /// <param name="ckt">The circuit</param>
        public override void Load(Circuit ckt)
        {
            var state  = ckt.State;
            var rstate = state.Real;
            var method = ckt.Method;

            double arg1, arg2, arg3, arg, argtf, c2, c4, capbc, capbe, cb, cbc, cbcn, cbe, cben, cbhat, cc, cchat, cdis, ceq, ceqbc,
                   ceqbe, ceqbx, ceqcs, cex, csat, ctot, czbc, czbcf2, czbe, czbef2, czbx, czbxf2, czcs, delvbc, delvbe, denom, dqbdvc,
                   dqbdve, evbc, evbcn, evbe, evben, f1, f2, f3, fcpc, fcpe, gbc, gbcn, gbe, gben, gccs, gcpr, gepr, geq, geqbx, geqcb,
                   gex, gm, gmu, go, gpi, gx, oik, oikr, ovtf, pc, pe, ps, q1, q2, qb, rbpi, rbpr, sarg, sqarg, td, temp, tf, tr, vbc,
                   vbe, vbx, vce, vcs, vt, vtc, vte, vtn, xjrb, xjtf, xmc, xme, xms, xtf, capbx = 0, capcs = 0;
            bool icheck, ichk1;

            vt = BJTtemp * Circuit.CONSTKoverQ;

            gccs  = 0;
            ceqcs = 0;
            geqbx = 0;
            ceqbx = 0;
            geqcb = 0;

            // dc model paramters
            csat = BJTtSatCur * BJTarea;
            rbpr = Model.BJTminBaseResist / BJTarea;
            rbpi = Model.BJTbaseResist / BJTarea - rbpr;
            gcpr = Model.BJTcollectorConduct * BJTarea;
            gepr = Model.BJTemitterConduct * BJTarea;
            oik  = Model.BJTinvRollOffF / BJTarea;
            c2   = BJTtBEleakCur * BJTarea;
            vte  = Model.BJTleakBEemissionCoeff * vt;
            oikr = Model.BJTinvRollOffR / BJTarea;
            c4   = BJTtBCleakCur * BJTarea;
            vtc  = Model.BJTleakBCemissionCoeff * vt;
            td   = Model.BJTexcessPhaseFactor;
            xjrb = Model.BJTbaseCurrentHalfResist * BJTarea;

            // initialization
            icheck = true;
            if (state.UseSmallSignal)
            {
                vbe = state.States[0][BJTstate + BJTvbe];
                vbc = state.States[0][BJTstate + BJTvbc];
                vbx = Model.BJTtype * (rstate.OldSolution[BJTbaseNode] - rstate.OldSolution[BJTcolPrimeNode]);
                vcs = Model.BJTtype * (rstate.OldSolution[BJTsubstNode] - rstate.OldSolution[BJTcolPrimeNode]);
            }
            else if (method != null && method.SavedTime == 0.0)
            {
                vbe = state.States[1][BJTstate + BJTvbe];
                vbc = state.States[1][BJTstate + BJTvbc];
                vbx = Model.BJTtype * (rstate.OldSolution[BJTbaseNode] - rstate.OldSolution[BJTcolPrimeNode]);
                vcs = Model.BJTtype * (rstate.OldSolution[BJTsubstNode] - rstate.OldSolution[BJTcolPrimeNode]);
                if (state.UseIC)
                {
                    vbx = Model.BJTtype * (BJTicVBE - BJTicVCE);
                    vcs = 0.0;
                }
            }
            else if (state.Init == CircuitState.InitFlags.InitJct && state.UseIC)
            {
                vbe = Model.BJTtype * BJTicVBE;
                vce = Model.BJTtype * BJTicVCE;
                vbc = vbe - vce;
                vbx = vbc;
                vcs = 0.0;
            }
            else if (state.Init == CircuitState.InitFlags.InitJct && !BJToff)
            {
                vbe = BJTtVcrit;
                vbc = 0.0;
                vcs = vbx = 0.0;
            }
            else if (state.Init == CircuitState.InitFlags.InitJct || (state.Init == CircuitState.InitFlags.InitFix && BJToff))
            {
                vbe = 0.0;
                vbc = 0.0;
                vcs = vbx = 0.0;
            }
            else
            {
                // compute new nonlinear branch voltages
                vbe    = Model.BJTtype * (rstate.OldSolution[BJTbasePrimeNode] - rstate.OldSolution[BJTemitPrimeNode]);
                vbc    = Model.BJTtype * (rstate.OldSolution[BJTbasePrimeNode] - rstate.OldSolution[BJTcolPrimeNode]);
                delvbe = vbe - state.States[0][BJTstate + BJTvbe];
                delvbc = vbc - state.States[0][BJTstate + BJTvbc];
                vbx    = Model.BJTtype * (rstate.OldSolution[BJTbaseNode] - rstate.OldSolution[BJTcolPrimeNode]);
                vcs    = Model.BJTtype * (rstate.OldSolution[BJTsubstNode] - rstate.OldSolution[BJTcolPrimeNode]);
                cchat  = state.States[0][BJTstate + BJTcc] + (state.States[0][BJTstate + BJTgm] + state.States[0][BJTstate + BJTgo]) * delvbe
                         - (state.States[0][BJTstate + BJTgo] + state.States[0][BJTstate + BJTgmu]) * delvbc;
                cbhat = state.States[0][BJTstate + BJTcb] + state.States[0][BJTstate + BJTgpi] * delvbe + state.States[0][BJTstate + BJTgmu] * delvbc;

                // limit nonlinear branch voltages
                ichk1 = true;
                vbe   = Semiconductor.pnjlim(vbe, state.States[0][BJTstate + BJTvbe], vt, BJTtVcrit, ref icheck);
                vbc   = Semiconductor.pnjlim(vbc, state.States[0][BJTstate + BJTvbc], vt, BJTtVcrit, ref ichk1);
                if (ichk1)
                {
                    icheck = true;
                }
            }

            // determine dc current and derivatives
            vtn = vt * Model.BJTemissionCoeffF;
            if (vbe > -5 * vtn)
            {
                evbe = Math.Exp(vbe / vtn);
                cbe  = csat * (evbe - 1) + state.Gmin * vbe;
                gbe  = csat * evbe / vtn + state.Gmin;
                if (c2 == 0)
                {
                    cben = 0;
                    gben = 0;
                }
                else
                {
                    evben = Math.Exp(vbe / vte);
                    cben  = c2 * (evben - 1);
                    gben  = c2 * evben / vte;
                }
            }
            else
            {
                gbe  = -csat / vbe + state.Gmin;
                cbe  = gbe * vbe;
                gben = -c2 / vbe;
                cben = gben * vbe;
            }
            vtn = vt * Model.BJTemissionCoeffR;
            if (vbc > -5 * vtn)
            {
                evbc = Math.Exp(vbc / vtn);
                cbc  = csat * (evbc - 1) + state.Gmin * vbc;
                gbc  = csat * evbc / vtn + state.Gmin;
                if (c4 == 0)
                {
                    cbcn = 0;
                    gbcn = 0;
                }
                else
                {
                    evbcn = Math.Exp(vbc / vtc);
                    cbcn  = c4 * (evbcn - 1);
                    gbcn  = c4 * evbcn / vtc;
                }
            }
            else
            {
                gbc  = -csat / vbc + state.Gmin;
                cbc  = gbc * vbc;
                gbcn = -c4 / vbc;
                cbcn = gbcn * vbc;
            }

            // determine base charge terms
            q1 = 1 / (1 - Model.BJTinvEarlyVoltF * vbc - Model.BJTinvEarlyVoltR * vbe);
            if (oik == 0 && oikr == 0)
            {
                qb     = q1;
                dqbdve = q1 * qb * Model.BJTinvEarlyVoltR;
                dqbdvc = q1 * qb * Model.BJTinvEarlyVoltF;
            }
            else
            {
                q2    = oik * cbe + oikr * cbc;
                arg   = Math.Max(0, 1 + 4 * q2);
                sqarg = 1;
                if (arg != 0)
                {
                    sqarg = Math.Sqrt(arg);
                }
                qb     = q1 * (1 + sqarg) / 2;
                dqbdve = q1 * (qb * Model.BJTinvEarlyVoltR + oik * gbe / sqarg);
                dqbdvc = q1 * (qb * Model.BJTinvEarlyVoltF + oikr * gbc / sqarg);
            }

            // weil's approx. for excess phase applied with backward-
            // euler integration
            cc  = 0;
            cex = cbe;
            gex = gbe;
            if (method != null && td != 0)
            {
                arg1  = method.Delta / td;
                arg2  = 3 * arg1;
                arg1  = arg2 * arg1;
                denom = 1 + arg1 + arg2;
                arg3  = arg1 / denom;
                if (method.SavedTime == 0.0)
                {
                    state.States[1][BJTstate + BJTcexbc] = cbe / qb;
                    state.States[2][BJTstate + BJTcexbc] = state.States[1][BJTstate + BJTcexbc];
                }
                cc = (state.States[1][BJTstate + BJTcexbc] * (1 + method.Delta / method.DeltaOld[1] + arg2) -
                      state.States[2][BJTstate + BJTcexbc] * method.Delta / method.DeltaOld[1]) / denom;
                cex = cbe * arg3;
                gex = gbe * arg3;
                state.States[0][BJTstate + BJTcexbc] = cc + cex / qb;
            }

            // determine dc incremental conductances
            cc = cc + (cex - cbc) / qb - cbc / BJTtBetaR - cbcn;
            cb = cbe / BJTtBetaF + cben + cbc / BJTtBetaR + cbcn;
            gx = rbpr + rbpi / qb;
            if (xjrb != 0)
            {
                arg1 = Math.Max(cb / xjrb, 1e-9);
                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 != 0)
            {
                gx = 1 / gx;
            }
            gpi = gbe / BJTtBetaF + gben;
            gmu = gbc / BJTtBetaR + gbcn;
            go  = (gbc + (cex - cbc) * dqbdvc / qb) / qb;
            gm  = (gex - (cex - cbc) * dqbdve / qb) / qb - go;

            if (method != null || state.UseIC || state.UseSmallSignal)
            {
                // charge storage elements
                tf   = Model.BJTtransitTimeF;
                tr   = Model.BJTtransitTimeR;
                czbe = BJTtBEcap * BJTarea;
                pe   = BJTtBEpot;
                xme  = Model.BJTjunctionExpBE;
                cdis = Model.BJTbaseFractionBCcap;
                ctot = BJTtBCcap * BJTarea;
                czbc = ctot * cdis;
                czbx = ctot - czbc;
                pc   = BJTtBCpot;
                xmc  = Model.BJTjunctionExpBC;
                fcpe = BJTtDepCap;
                czcs = Model.BJTcapCS * BJTarea;
                ps   = Model.BJTpotentialSubstrate;
                xms  = Model.BJTexponentialSubstrate;
                xtf  = Model.BJTtransitTimeBiasCoeffF;
                ovtf = Model.BJTtransitTimeVBCFactor;
                xjtf = Model.BJTtransitTimeHighCurrentF * BJTarea;
                if (tf != 0 && vbe > 0)
                {
                    argtf = 0;
                    arg2  = 0;
                    arg3  = 0;
                    if (xtf != 0)
                    {
                        argtf = xtf;
                        if (ovtf != 0)
                        {
                            argtf = argtf * Math.Exp(vbc * ovtf);
                        }
                        arg2 = argtf;
                        if (xjtf != 0)
                        {
                            temp  = cbe / (cbe + xjtf);
                            argtf = argtf * temp * temp;
                            arg2  = argtf * (3 - temp - temp);
                        }
                        arg3 = cbe * argtf * ovtf;
                    }
                    cbe   = cbe * (1 + argtf) / qb;
                    gbe   = (gbe * (1 + arg2) - cbe * dqbdve) / qb;
                    geqcb = tf * (arg3 - cbe * dqbdvc) / qb;
                }
                if (vbe < fcpe)
                {
                    arg  = 1 - vbe / pe;
                    sarg = Math.Exp(-xme * Math.Log(arg));
                    state.States[0][BJTstate + BJTqbe] = tf * cbe + pe * czbe *
                                                         (1 - arg * sarg) / (1 - xme);
                    capbe = tf * gbe + czbe * sarg;
                }
                else
                {
                    f1     = BJTtf1;
                    f2     = Model.BJTf2;
                    f3     = Model.BJTf3;
                    czbef2 = czbe / f2;
                    state.States[0][BJTstate + BJTqbe] = tf * cbe + czbe * f1 + czbef2 * (f3 * (vbe - fcpe) + (xme / (pe + pe)) * (vbe * vbe - fcpe * fcpe));
                    capbe = tf * gbe + czbef2 * (f3 + xme * vbe / pe);
                }
                fcpc = BJTtf4;
                f1   = BJTtf5;
                f2   = Model.BJTf6;
                f3   = Model.BJTf7;
                if (vbc < fcpc)
                {
                    arg  = 1 - vbc / pc;
                    sarg = Math.Exp(-xmc * Math.Log(arg));
                    state.States[0][BJTstate + BJTqbc] = tr * cbc + pc * czbc * (1 - arg * sarg) / (1 - xmc);
                    capbc = tr * gbc + czbc * sarg;
                }
                else
                {
                    czbcf2 = czbc / f2;
                    state.States[0][BJTstate + BJTqbc] = 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));
                    state.States[0][BJTstate + BJTqbx] = pc * czbx * (1 - arg * sarg) / (1 - xmc);
                    capbx = czbx * sarg;
                }
                else
                {
                    czbxf2 = czbx / f2;
                    state.States[0][BJTstate + BJTqbx] = 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));
                    state.States[0][BJTstate + BJTqcs] = ps * czcs * (1 - arg * sarg) / (1 - xms);
                    capcs = czcs * sarg;
                }
                else
                {
                    state.States[0][BJTstate + BJTqcs] = vcs * czcs * (1 + xms * vcs / (2 * ps));
                    capcs = czcs * (1 + xms * vcs / ps);
                }
                BJTcapbe = capbe;
                BJTcapbc = capbc;
                BJTcapcs = capcs;
                BJTcapbx = capbx;

                // store small-signal parameters
                if (state.UseSmallSignal)
                {
                    state.States[0][BJTstate + BJTcqbe]  = capbe;
                    state.States[0][BJTstate + BJTcqbc]  = capbc;
                    state.States[0][BJTstate + BJTcqcs]  = capcs;
                    state.States[0][BJTstate + BJTcqbx]  = capbx;
                    state.States[0][BJTstate + BJTcexbc] = geqcb;
                    return; /* go to 1000 */
                }

                // transient analysis
                if (method != null)
                {
                    var result = method.Integrate(state, BJTstate + BJTqbe, capbe);
                    geq    = result.Geq;
                    ceq    = result.Ceq;
                    geqcb  = geqcb * method.Slope;
                    gpi    = gpi + geq;
                    cb     = cb + state.States[0][BJTstate + BJTcqbe];
                    result = method.Integrate(state, BJTstate + BJTqbc, capbc);
                    geq    = result.Geq;
                    ceq    = result.Ceq;
                    gmu    = gmu + geq;
                    cb     = cb + state.States[0][BJTstate + BJTcqbc];
                    cc     = cc - state.States[0][BJTstate + BJTcqbc];
                }
            }

            // check convergence
            if (state.Init != CircuitState.InitFlags.InitFix || !BJToff)
            {
                if (icheck)
                {
                    state.IsCon = false;
                }
            }

            // charge storage for c-s and b-x junctions
            if (method != null)
            {
                var result = method.Integrate(state, BJTstate + BJTqcs, capcs);
                gccs   = result.Geq;
                ceq    = result.Ceq;
                result = method.Integrate(state, BJTstate + BJTqbx, capbx);
                geqbx  = result.Geq;
                ceq    = result.Ceq;
            }

            // Store all states
            state.States[0][BJTstate + BJTvbe]   = vbe;
            state.States[0][BJTstate + BJTvbc]   = vbc;
            state.States[0][BJTstate + BJTcc]    = cc;
            state.States[0][BJTstate + BJTcb]    = cb;
            state.States[0][BJTstate + BJTgpi]   = gpi;
            state.States[0][BJTstate + BJTgmu]   = gmu;
            state.States[0][BJTstate + BJTgm]    = gm;
            state.States[0][BJTstate + BJTgo]    = go;
            state.States[0][BJTstate + BJTgx]    = gx;
            state.States[0][BJTstate + BJTgeqcb] = geqcb;
            state.States[0][BJTstate + BJTgccs]  = gccs;
            state.States[0][BJTstate + BJTgeqbx] = geqbx;

            // load current excitation vector
            ceqcs = Model.BJTtype * (state.States[0][BJTstate + BJTcqcs] - vcs * gccs);
            ceqbx = Model.BJTtype * (state.States[0][BJTstate + BJTcqbx] - vbx * geqbx);
            ceqbe = Model.BJTtype * (cc + cb - vbe * (gm + go + gpi) + vbc * (go - geqcb));
            ceqbc = Model.BJTtype * (-cc + vbe * (gm + go) - vbc * (gmu + go));

            rstate.Rhs[BJTbaseNode]      += (-ceqbx);
            rstate.Rhs[BJTcolPrimeNode]  += (ceqcs + ceqbx + ceqbc);
            rstate.Rhs[BJTbasePrimeNode] += (-ceqbe - ceqbc);
            rstate.Rhs[BJTemitPrimeNode] += (ceqbe);
            rstate.Rhs[BJTsubstNode]     += (-ceqcs);

            // load y matrix
            rstate.Matrix[BJTcolNode, BJTcolNode]             += (gcpr);
            rstate.Matrix[BJTbaseNode, BJTbaseNode]           += (gx + geqbx);
            rstate.Matrix[BJTemitNode, BJTemitNode]           += (gepr);
            rstate.Matrix[BJTcolPrimeNode, BJTcolPrimeNode]   += (gmu + go + gcpr + gccs + geqbx);
            rstate.Matrix[BJTbasePrimeNode, BJTbasePrimeNode] += (gx + gpi + gmu + geqcb);
            rstate.Matrix[BJTemitPrimeNode, BJTemitPrimeNode] += (gpi + gepr + gm + go);
            rstate.Matrix[BJTcolNode, BJTcolPrimeNode]        += (-gcpr);
            rstate.Matrix[BJTbaseNode, BJTbasePrimeNode]      += (-gx);
            rstate.Matrix[BJTemitNode, BJTemitPrimeNode]      += (-gepr);
            rstate.Matrix[BJTcolPrimeNode, BJTcolNode]        += (-gcpr);
            rstate.Matrix[BJTcolPrimeNode, BJTbasePrimeNode]  += (-gmu + gm);
            rstate.Matrix[BJTcolPrimeNode, BJTemitPrimeNode]  += (-gm - go);
            rstate.Matrix[BJTbasePrimeNode, BJTbaseNode]      += (-gx);
            rstate.Matrix[BJTbasePrimeNode, BJTcolPrimeNode]  += (-gmu - geqcb);
            rstate.Matrix[BJTbasePrimeNode, BJTemitPrimeNode] += (-gpi);
            rstate.Matrix[BJTemitPrimeNode, BJTemitNode]      += (-gepr);
            rstate.Matrix[BJTemitPrimeNode, BJTcolPrimeNode]  += (-go + geqcb);
            rstate.Matrix[BJTemitPrimeNode, BJTbasePrimeNode] += (-gpi - gm - geqcb);
            rstate.Matrix[BJTsubstNode, BJTsubstNode]         += (gccs);
            rstate.Matrix[BJTcolPrimeNode, BJTsubstNode]      += (-gccs);
            rstate.Matrix[BJTsubstNode, BJTcolPrimeNode]      += (-gccs);
            rstate.Matrix[BJTbaseNode, BJTcolPrimeNode]       += (-geqbx);
            rstate.Matrix[BJTcolPrimeNode, BJTbaseNode]       += (-geqbx);
        }
예제 #16
0
        /// <include file='../common/docs.xml' path='docs/methods/Initialize/*'/>
        protected void Initialize(out double vgs, out double vds, out double vbs, out bool check)
        {
            check = true;

            if (_iteration.Mode == IterationModes.Float || (_method != null && _method.BaseTime.Equals(0.0)) ||
                _iteration.Mode == IterationModes.Fix && !Parameters.Off)
            {
                // General iteration
                var s = _variables.SourcePrime.Value;
                vbs = ModelParameters.MosfetType * (_variables.Bulk.Value - s);
                vgs = ModelParameters.MosfetType * (_variables.Gate.Value - s);
                vds = ModelParameters.MosfetType * (_variables.DrainPrime.Value - s);

                // now some common crunching for some more useful quantities
                var vbd  = vbs - vds;
                var vgd  = vgs - vds;
                var vgdo = Vgs - Vds;
                var von  = ModelParameters.MosfetType * Von;

                /*
                 * limiting
                 * we want to keep device voltages from changing
                 * so fast that the exponentials churn out overflows
                 * and similar rudeness
                 */
                // NOTE: Spice 3f5 does not write out Vgs during DC analysis, so DEVfetlim may give different results in Spice 3f5
                if (Vds >= 0)
                {
                    vgs = Transistor.LimitFet(vgs, Vgs, von);
                    vds = vgs - vgd;
                    vds = Transistor.LimitVds(vds, Vds);
                }
                else
                {
                    vgd = Transistor.LimitFet(vgd, vgdo, von);
                    vds = vgs - vgd;
                    vds = -Transistor.LimitVds(-vds, -Vds);
                    vgs = vgd + vds;
                }

                check = false;
                if (vds >= 0)
                {
                    vbs = Semiconductor.LimitJunction(vbs, Vbs, Properties.TempVt, SourceVCritical, ref check);
                }
                else
                {
                    vbd = Semiconductor.LimitJunction(vbd, Vbd, Properties.TempVt, DrainVCritical, ref check);
                    vbs = vbd + vds;
                }
            }
            else
            {
                /* ok - not one of the simple cases, so we have to
                 * look at all of the possibilities for why we were
                 * called.  We still just initialize the three voltages
                 */
                if (_iteration.Mode == IterationModes.Junction && !Parameters.Off)
                {
                    vds = ModelParameters.MosfetType * Parameters.InitialVds;
                    vgs = ModelParameters.MosfetType * Parameters.InitialVgs;
                    vbs = ModelParameters.MosfetType * Parameters.InitialVbs;

                    // TODO: At some point, check what this is supposed to do
                    if (vds.Equals(0) && vgs.Equals(0) && vbs.Equals(0) && (_time == null || _time.UseDc || !_time.UseIc))
                    {
                        vbs = -1;
                        vgs = ModelParameters.MosfetType * Properties.TempVt0;
                        vds = 0;
                    }
                }
                else
                {
                    vbs = vgs = vds = 0;
                }
            }
        }
예제 #17
0
        /// <summary>
        /// Load the behavior
        /// </summary>
        /// <param name="simulation">Simulation</param>
        void IBiasingBehavior.Load()
        {
            var    state = _state;
            double capbd = 0.0;
            double capbs = 0.0;
            double cdgb  = 0.0;
            double cddb  = 0.0;
            double cdsb  = 0.0;
            double csgb  = 0.0;
            double cssb  = 0.0;
            double csdb  = 0.0;
            double qdrn  = 0.0;
            double qsrc  = 0.0;

            double[] args = new double[8];
            bool     chargeComputationsNeeded = TranBehavior != null;

            double EffectiveLength = BaseParameters.Length - ModelParameters.DeltaL * 1.0e-6;
            double DrainArea       = BaseParameters.DrainArea;
            double SourceArea      = BaseParameters.SourceArea;
            double DrainPerimeter  = BaseParameters.DrainPerimeter;
            double SourcePerimeter = BaseParameters.SourcePerimeter;
            double DrainSatCurrent;

            if ((DrainSatCurrent = DrainArea * ModelParameters.JctSatCurDensity)
                < 1e-15)
            {
                DrainSatCurrent = 1.0e-15;
            }

            double SourceSatCurrent;

            if ((SourceSatCurrent = SourceArea * ModelParameters.JctSatCurDensity)
                < 1.0e-15)
            {
                SourceSatCurrent = 1.0e-15;
            }

            double GateSourceOverlapCap = ModelParameters.GateSourceOverlapCap * BaseParameters.Width;
            double GateDrainOverlapCap  = ModelParameters.GateDrainOverlapCap * BaseParameters.Width;
            double GateBulkOverlapCap   = ModelParameters.GateBulkOverlapCap * EffectiveLength;
            double von   = ModelParameters.Type * Von;
            double vdsat = ModelParameters.Type * Vdsat;
            double vt0   = ModelParameters.Type * Vt0;
            bool   Check = true;
            double vbd;
            double vbs;
            double vds;
            double vgd;
            double vgs;

            if (Simulation is FrequencySimulation && !state.UseDc)
            {
                vbs = this.Vbs;
                vgs = this.Vgs;
                vds = this.Vds;
                chargeComputationsNeeded = true;
            }
            else if (state.Init == InitializationModes.Junction && !BaseParameters.Off)
            {
                vds = ModelParameters.Type * BaseParameters.IcVDS;
                vgs = ModelParameters.Type * BaseParameters.IcVGS;
                vbs = ModelParameters.Type * BaseParameters.IcVBS;
                if ((vds == 0) && (vgs == 0) && (vbs == 0) &&
                    (state.UseDc || TranBehavior != null || !state.UseIc))
                {
                    vbs = -1;
                    vgs = vt0;
                    vds = 0;
                }
            }
            else if ((state.Init == InitializationModes.Junction ||
                      state.Init == InitializationModes.Fix) && (BaseParameters.Off))
            {
                vbs = vgs = vds = 0;
            }
            else
            {
                vbs = ModelParameters.Type * (state.Solution[BulkNode] - state.Solution[SourceNodePrime]);
                vgs = ModelParameters.Type * (state.Solution[GateNode] - state.Solution[SourceNodePrime]);
                vds = ModelParameters.Type * (state.Solution[DrainNodePrime] - state.Solution[SourceNodePrime]);
                vbd = vbs - vds;
                vgd = vgs - vds;
                double vgdo = this.Vgs - this.Vds;

                von = ModelParameters.Type * base.Von;
                if (this.Vds >= 0)
                {
                    vgs = Transistor.LimitFet(vgs, this.Vgs, von);
                    vds = vgs - vgd;
                    vds = Transistor.LimitVds(vds, this.Vds);
                    vgd = vgs - vds;
                }
                else
                {
                    vgd = Transistor.LimitFet(vgd, vgdo, von);
                    vds = vgs - vgd;
                    vds = -Transistor.LimitVds(-vds, -this.Vds);
                    vgs = vgd + vds;
                }

                Check = false;
                double vcrit;
                if (vds >= 0)
                {
                    vcrit = Constants.Vt0 * Math.Log(Constants.Vt0 / (Constants.Root2 * SourceSatCurrent));
                    vbs   = Semiconductor.LimitJunction(vbs, this.Vbs, Constants.Vt0, vcrit, ref Check); /* B1 test */
                    vbd   = vbs - vds;
                }
                else
                {
                    vcrit = Constants.Vt0 * Math.Log(Constants.Vt0 / (Constants.Root2 * DrainSatCurrent));
                    vbd   = Semiconductor.LimitJunction(vbd, this.Vbd, Constants.Vt0, vcrit, ref Check); /* B1 test*/
                    vbs   = vbd + vds;
                }
            }

            /* determine DC current and derivatives */
            vbd = vbs - vds;
            vgd = vgs - vds;
            double vgb = vgs - vbs;
            double cbs;
            double gbs;

            if (vbs <= 0.0)
            {
                gbs = SourceSatCurrent / Constants.Vt0 + BaseConfiguration.Gmin;
                cbs = gbs * vbs;
            }
            else
            {
                double evbs = Math.Exp(vbs / Constants.Vt0);
                gbs = SourceSatCurrent * evbs / Constants.Vt0 + BaseConfiguration.Gmin;
                cbs = SourceSatCurrent * (evbs - 1) + BaseConfiguration.Gmin * vbs;
            }

            double cbd;
            double gbd;

            if (vbd <= 0.0)
            {
                gbd = DrainSatCurrent / Constants.Vt0 + BaseConfiguration.Gmin;
                cbd = gbd * vbd;
            }
            else
            {
                double evbd = Math.Exp(vbd / Constants.Vt0);
                gbd = DrainSatCurrent * evbd / Constants.Vt0 + BaseConfiguration.Gmin;
                cbd = DrainSatCurrent * (evbd - 1) + BaseConfiguration.Gmin * vbd;
            }

            /* line 400 */
            if (vds >= 0)
            {
                /* normal mode */
                this.Mode = 1;
            }
            else
            {
                /* inverse mode */
                this.Mode = -1;
            }

            double cdrain;
            double gds;
            double gm;
            double gmbs;
            double cgdb;
            double cgsb;
            double cbdb;
            double cggb;
            double cbgb;
            double cbsb;
            double qgate;
            double qbulk;

            /* call B1evaluate to calculate drain current and its
             * derivatives and charge and capacitances related to gate
             * drain, and bulk
             */
            if (vds >= 0)
            {
                Evaluate(chargeComputationsNeeded,
                         vds, vbs, vgs, out gm, out gds, out gmbs, out qgate,
                         out qbulk, out qdrn, out cggb, out cgdb, out cgsb, out cbgb, out cbdb, out cbsb, out cdgb,
                         out cddb, out cdsb, out cdrain, out von, out vdsat);
            }
            else
            {
                Evaluate(chargeComputationsNeeded,
                         -vds, vbd, vgd, out gm, out gds, out gmbs, out qgate,
                         out qbulk, out qsrc, out cggb, out cgsb, out cgdb, out cbgb, out cbsb, out cbdb, out csgb,
                         out cssb, out csdb, out cdrain, out von, out vdsat);
            }

            base.Von   = ModelParameters.Type * von;
            this.Vdsat = ModelParameters.Type * vdsat;

            /*
             *  COMPUTE EQUIVALENT DRAIN CURRENT SOURCE
             */
            double cd = Mode * cdrain - cbd;

            if (chargeComputationsNeeded)
            {
                /*
                 *  charge storage elements
                 *
                 *   bulk-drain and bulk-source depletion capacitances
                 *  czbd : zero bias drain junction capacitance
                 *  czbs : zero bias source junction capacitance
                 * czbdsw:zero bias drain junction sidewall capacitance
                 * czbssw:zero bias source junction sidewall capacitance
                 */

                double czbd   = ModelParameters.UnitAreaJctCap * DrainArea;
                double czbs   = ModelParameters.UnitAreaJctCap * SourceArea;
                double czbdsw = ModelParameters.UnitLengthSidewallJctCap * DrainPerimeter;
                double czbssw = ModelParameters.UnitLengthSidewallJctCap * SourcePerimeter;
                double PhiB   = ModelParameters.BulkJctPotential;
                double PhiBSW = ModelParameters.SidewallJctPotential;
                double MJ     = ModelParameters.BulkJctBotGradingCoeff;
                double MJSW   = ModelParameters.BulkJctSideGradingCoeff;
                double arg;
                double sarg;
                double sargsw;
                double argsw;
                /* Source Bulk Junction */
                if (vbs < 0)
                {
                    arg      = 1 - vbs / PhiB;
                    argsw    = 1 - vbs / PhiBSW;
                    sarg     = Math.Exp(-MJ * Math.Log(arg));
                    sargsw   = Math.Exp(-MJSW * Math.Log(argsw));
                    this.Qbs = PhiB * czbs * (1 - arg * sarg) / (1 - MJ) +
                               PhiBSW * czbssw * (1 - argsw * sargsw) / (1 - MJSW);
                    capbs = czbs * sarg + czbssw * sargsw;
                }
                else
                {
                    this.Qbs = vbs * (czbs + czbssw) +
                               vbs * vbs * (czbs * MJ * 0.5 / PhiB + czbssw * MJSW * 0.5 / PhiBSW);
                    capbs = czbs + czbssw + vbs * (czbs * MJ / PhiB + czbssw * MJSW / PhiBSW);
                }

                /* Drain Bulk Junction */
                if (vbd < 0)
                {
                    arg    = 1 - vbd / PhiB;
                    argsw  = 1 - vbd / PhiBSW;
                    sarg   = Math.Exp(-MJ * Math.Log(arg));
                    sargsw = Math.Exp(-MJSW * Math.Log(argsw));

                    this.Qbd = PhiB * czbd * (1 - arg * sarg) / (1 - MJ) +
                               PhiBSW * czbdsw * (1 - argsw * sargsw) / (1 - MJSW);
                    capbd = czbd * sarg + czbdsw * sargsw;
                }
                else
                {
                    this.Qbd = vbd * (czbd + czbdsw) +
                               vbd * vbd * (czbd * MJ * 0.5 / PhiB + czbdsw * MJSW * 0.5 / PhiBSW);
                    capbd = czbd + czbdsw + vbd * (czbd * MJ / PhiB + czbdsw * MJSW / PhiBSW);
                }
            }

            /*
             *  check convergence
             */
            if ((!BaseParameters.Off) || state.Init != InitializationModes.Fix)
            {
                if (Check)
                {
                    state.IsConvergent = false;
                }
            }

            this.Vbs  = vbs;
            this.Vbd  = vbd;
            this.Vgs  = vgs;
            this.Vds  = vds;
            this.Cd   = cd;
            this.Cbs  = cbs;
            this.Cbd  = cbd;
            this.Gm   = gm;
            this.Gds  = gds;
            this.Gmbs = gmbs;
            this.Gbd  = gbd;
            this.Gbs  = gbs;

            this.Cggb = cggb;
            this.Cgdb = cgdb;
            this.Cgsb = cgsb;

            this.Cbgb = cbgb;
            this.Cbdb = cbdb;
            this.Cbsb = cbsb;

            this.Cdgb = cdgb;
            this.Cddb = cddb;
            this.Cdsb = cdsb;

            this.Capbs = capbs;
            this.Capbd = capbd;

            /* bulk and channel charge plus overlaps */
            // if (!(ckt->CKTmode & (MODETRAN | MODEAC)) && (!(ckt->CKTmode & MODETRANOP) || !(ckt->CKTmode & MODEUIC)) && !(ckt->CKTmode & MODEINITSMSIG))
            if (!chargeComputationsNeeded)
            {
                goto line850;
            }
            double gcbdb;
            double gcbgb;
            double gcbsb;
            double gcddb;
            double gcdgb;
            double gcdsb;
            double gcgdb;
            double gcggb;
            double gcgsb;
            double gcsdb;
            double gcsgb;
            double gcssb;

            // line755:
            if (this.Mode > 0)
            {
                args[0] = GateDrainOverlapCap;
                args[1] = GateSourceOverlapCap;
                args[2] = GateBulkOverlapCap;
                args[3] = capbd;
                args[4] = capbs;
                args[5] = cggb;
                args[6] = cgdb;
                args[7] = cgsb;

                MosCap(vgd, vgs, vgb,
                       args,

                       /*
                        * GateDrainOverlapCap,
                        * GateSourceOverlapCap,GateBulkOverlapCap,
                        * capbd,capbs,
                        *          cggb,cgdb,cgsb,
                        */
                       cbgb, cbdb, cbsb,
                       cdgb, cddb, cdsb,
                       out gcggb, out gcgdb, out gcgsb,
                       out gcbgb, out gcbdb, out gcbsb,
                       out gcdgb, out gcddb, out gcdsb, out gcsgb, out gcsdb, out gcssb,
                       ref qgate, ref qbulk,
                       ref qdrn, out qsrc);
            }
            else
            {
                args[0] = GateSourceOverlapCap;
                args[1] = GateDrainOverlapCap;
                args[2] = GateBulkOverlapCap;
                args[3] = capbs;
                args[4] = capbd;
                args[5] = cggb;
                args[6] = cgsb;
                args[7] = cgdb;

                MosCap(vgs, vgd, vgb,
                       args,

                       /*
                        * GateSourceOverlapCap,
                        * GateDrainOverlapCap,GateBulkOverlapCap,
                        * capbs,capbd,
                        * cggb,cgsb,cgdb,
                        */
                       cbgb, cbsb, cbdb,
                       csgb, cssb, csdb,
                       out gcggb, out gcgsb, out gcgdb,
                       out gcbgb, out gcbsb, out gcbdb,
                       out gcsgb, out gcssb, out gcsdb, out gcdgb, out gcdsb, out gcddb,
                       ref qgate, ref qbulk,
                       ref qsrc, out qdrn);
            }

            // store small signal parameters
            // if ((!(ckt->CKTmode & (MODEAC | MODETRAN))) && (ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))
            // goto line850;

            if (Simulation is FrequencySimulation && !state.UseDc)
            {
                this.Cggb  = cggb;
                this.Cgdb  = cgdb;
                this.Cgsb  = cgsb;
                this.Cbgb  = cbgb;
                this.Cbdb  = cbdb;
                this.Cbsb  = cbsb;
                this.Cdgb  = cdgb;
                this.Cddb  = cddb;
                this.Cdsb  = cdsb;
                this.Capbd = capbd;
                this.Capbs = capbs;
                goto line1000;
            }

            if (TranBehavior != null)
            {
                TranBehavior.Qg.Current = qgate;
                TranBehavior.Qd.Current = qdrn - this.Qbd;
                TranBehavior.Qb.Current = qbulk + this.Qbd + this.Qbs;

                if (!state.UseDc)
                {
                    TranBehavior.Qb.Integrate();
                    TranBehavior.Qg.Integrate();
                    TranBehavior.Qd.Integrate();
                }
            }

            goto line860;
line850:
            /* initialize to zero charge conductance and current */
            double ceqqd;
            double ceqqg;
            double ceqqb;

            ceqqg = ceqqb = ceqqd = 0.0;
            gcdgb = gcddb = gcdsb = 0.0;
            gcsgb = gcsdb = gcssb = 0.0;
            gcggb = gcgdb = gcgsb = 0.0;
            gcbgb = gcbdb = gcbsb = 0.0;
            goto line900;
line860:
            /* evaluate equivalent charge current */
            double cqgate = TranBehavior.Qg.Derivative;
            double cqbulk = TranBehavior.Qb.Derivative;
            double cqdrn  = TranBehavior.Qd.Derivative;

            ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs;
            ceqqb = cqbulk - gcbgb * vgb + gcbdb * vbd + gcbsb * vbs;
            ceqqd = cqdrn - gcdgb * vgb + gcddb * vbd + gcdsb * vbs;
            double ceqbs;

            /*
             *  load current vector
             */
line900:
            ceqbs = ModelParameters.Type * (cbs - (gbs - BaseConfiguration.Gmin) * vbs);
            double ceqbd = ModelParameters.Type * (cbd - (gbd - BaseConfiguration.Gmin) * vbd);

            ceqqg = ModelParameters.Type * ceqqg;
            ceqqb = ModelParameters.Type * ceqqb;
            ceqqd = ModelParameters.Type * ceqqd;
            double cdreq;
            double xnrm;
            double xrev;

            if (this.Mode >= 0)
            {
                xnrm  = 1;
                xrev  = 0;
                cdreq = ModelParameters.Type * (cdrain - gds * vds - gm * vgs - gmbs * vbs);
            }
            else
            {
                xnrm  = 0;
                xrev  = 1;
                cdreq = -(ModelParameters.Type) * (cdrain + gds * vds - gm * vgd - gmbs * vbd);
            }

            var m = BaseParameters.Multiplier;

            GateNodePtr.Value        -= m * ceqqg;
            BulkNodePtr.Value        -= m * (ceqbs + ceqbd + ceqqb);
            DrainNodePrimePtr.Value  += m * (ceqbd - cdreq - ceqqd);
            SourceNodePrimePtr.Value += m * (cdreq + ceqbs + ceqqg + ceqqb + ceqqd);

            /*
             *  load y matrix
             */
            DdPtr.Value   += m * (base.DrainConductance);
            GgPtr.Value   += m * (gcggb);
            SsPtr.Value   += m * (base.SourceConductance);
            BbPtr.Value   += m * (gbd + gbs - gcbgb - gcbdb - gcbsb);
            DPdpPtr.Value += m * (base.DrainConductance + gds + gbd + xrev * (gm + gmbs) + gcddb);
            SPspPtr.Value += m * (base.SourceConductance + gds + gbs + xnrm * (gm + gmbs) + gcssb);
            DdpPtr.Value  += m * (-base.DrainConductance);
            GbPtr.Value   += m * (-gcggb - gcgdb - gcgsb);
            GdpPtr.Value  += m * (gcgdb);
            GspPtr.Value  += m * (gcgsb);
            SspPtr.Value  += m * (-base.SourceConductance);
            BgPtr.Value   += m * (gcbgb);
            BdpPtr.Value  += m * (-gbd + gcbdb);
            BspPtr.Value  += m * (-gbs + gcbsb);
            DPdPtr.Value  += m * (-base.DrainConductance);
            DPgPtr.Value  += m * ((xnrm - xrev) * gm + gcdgb);
            DPbPtr.Value  += m * (-gbd + (xnrm - xrev) * gmbs - gcdgb - gcddb - gcdsb);
            DPspPtr.Value += m * (-gds - xnrm * (gm + gmbs) + gcdsb);
            SPgPtr.Value  += m * (-(xnrm - xrev) * gm + gcsgb);
            SPsPtr.Value  += m * (-base.SourceConductance);
            SPbPtr.Value  += m * (-gbs - (xnrm - xrev) * gmbs - gcsgb - gcsdb - gcssb);
            SPdpPtr.Value += m * (-gds - xrev * (gm + gmbs) + gcsdb);

            line1000 :;
        }