コード例 #1
0
        /// <summary>
        /// Execute behavior
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            var    state = simulation.RealState;
            double value;

            PosBranchPtr.Value += 1;
            BranchPosPtr.Value += 1;
            NegBranchPtr.Value -= 1;
            BranchNegPtr.Value -= 1;

            if (simulation is TimeSimulation)
            {
                // Use the waveform if possible
                if (BaseParameters.Waveform != null)
                {
                    value = BaseParameters.Waveform.Value;
                }
                else
                {
                    value = BaseParameters.DcValue * state.SourceFactor;
                }
            }
            else
            {
                value = BaseParameters.DcValue * state.SourceFactor;
            }

            Voltage          = value;
            BranchPtr.Value += value;
        }
コード例 #2
0
        /// <summary>
        /// Perform temperature-dependent calculations.
        /// </summary>
        /// <param name="simulation">The base simulation.</param>
        /// <exception cref="NotImplementedException"></exception>
        public override void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            if (_mbp.NominalTemperature.Given)
            {
                _mbp.NominalTemperature.RawValue = simulation.RealState.NominalTemperature;
            }

            var vtnom  = Constants.KOverQ * _mbp.NominalTemperature;
            var fact1  = _mbp.NominalTemperature / Constants.ReferenceTemperature;
            var kt1    = Constants.Boltzmann * _mbp.NominalTemperature;
            var egfet1 = 1.16 - (7.02e-4 * _mbp.NominalTemperature * _mbp.NominalTemperature) /
                         (_mbp.NominalTemperature + 1108);
            var arg1    = -egfet1 / (kt1 + kt1) + 1.1150877 / (Constants.Boltzmann * 2 * Constants.ReferenceTemperature);
            var pbfact1 = -2 * vtnom * (1.5 * Math.Log(fact1) + Constants.Charge * arg1);

            Pbo = (_mbp.GatePotential - pbfact1) / fact1;
            var gmaold = (_mbp.GatePotential - Pbo) / Pbo;

            Cjfact = 1 / (1 + .5 * (4e-4 * (_mbp.NominalTemperature - Constants.ReferenceTemperature) - gmaold));

            if (_mbp.DepletionCapCoefficient > 0.95)
            {
                CircuitWarning.Warning(this,
                                       "{0}: Depletion capacitance coefficient too large, limited to 0.95".FormatString(Name));
                _mbp.DepletionCapCoefficient.Value = .95;
            }

            Xfc = Math.Log(1 - _mbp.DepletionCapCoefficient);
            F2  = Math.Exp((1 + 0.5) * Xfc);
            F3  = 1 - _mbp.DepletionCapCoefficient * (1 + 0.5);
            /* Modification for Sydney University JFET model */
            BFactor = (1 - _mbp.B) / (_mbp.GatePotential - _mbp.Threshold);
        }
コード例 #3
0
ファイル: BiasingBehavior.cs プロジェクト: ewiebe1/SpiceSharp
        /// <summary>
        /// Execute behavior
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            var    state = simulation.RealState;
            double value;

            // Time domain analysis
            if (simulation is TimeSimulation)
            {
                // Use the waveform if possible
                if (BaseParameters.Waveform != null)
                {
                    value = BaseParameters.Waveform.Value;
                }
                else
                {
                    value = BaseParameters.DcValue * state.SourceFactor;
                }
            }
            else
            {
                // AC or DC analysis use the DC value
                value = BaseParameters.DcValue * state.SourceFactor;
            }

            // NOTE: Spice 3f5's documentation is IXXXX POS NEG VALUE but in the code it is IXXXX NEG POS VALUE
            // I solved it by inverting the current when loading the rhs vector
            PosPtr.Value -= value;
            NegPtr.Value += value;
            Current       = value;
        }
コード例 #4
0
ファイル: BiasingBehavior.cs プロジェクト: ewiebe1/SpiceSharp
        // TODO: I believe this method of checking convergence can be improved. These calculations seem to be common for multiple behaviors.
        /// <summary>
        /// Check if the BJT is convergent
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        /// <returns></returns>
        public bool IsConvergent(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            var state  = simulation.RealState;
            var vbe    = ModelParameters.BipolarType * (state.Solution[BasePrimeNode] - state.Solution[EmitterPrimeNode]);
            var vbc    = ModelParameters.BipolarType * (state.Solution[BasePrimeNode] - state.Solution[CollectorPrimeNode]);
            var delvbe = vbe - VoltageBe;
            var delvbc = vbc - VoltageBe;
            var cchat  = CollectorCurrent + (Transconductance + OutputConductance) * delvbe - (OutputConductance + ConductanceMu) * delvbc;
            var cbhat  = BaseCurrent + ConductancePi * delvbe + ConductanceMu * delvbc;
            var cc     = CollectorCurrent;
            var cb     = BaseCurrent;

            // Check convergence
            var tol = BaseConfiguration.RelativeTolerance * Math.Max(Math.Abs(cchat), Math.Abs(cc)) + BaseConfiguration.AbsoluteTolerance;

            if (Math.Abs(cchat - cc) > tol)
            {
                state.IsConvergent = false;
                return(false);
            }

            tol = BaseConfiguration.RelativeTolerance * Math.Max(Math.Abs(cbhat), Math.Abs(cb)) + BaseConfiguration.AbsoluteTolerance;
            if (Math.Abs(cbhat - cb) > tol)
            {
                state.IsConvergent = false;
                return(false);
            }
            return(true);
        }
コード例 #5
0
        /// <summary>
        /// Execute behavior
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            double factor;
            double resistance = BaseParameters.Resistance;

            // Default Value Processing for Resistor Instance
            if (!BaseParameters.Temperature.Given)
            {
                BaseParameters.Temperature.RawValue = simulation.RealState.Temperature;
            }
            if (!BaseParameters.Width.Given)
            {
                BaseParameters.Width.RawValue = ModelParameters?.DefaultWidth ?? 0.0;
            }

            if (ModelParameters != null)
            {
                if (!BaseParameters.Resistance.Given)
                {
                    if (ModelParameters.SheetResistance.Given && ModelParameters.SheetResistance > 0 && BaseParameters.Length > 0)
                    {
                        resistance = ModelParameters.SheetResistance * (BaseParameters.Length - ModelParameters.Narrow) / (BaseParameters.Width - ModelParameters.Narrow);
                    }
                    else
                    {
                        CircuitWarning.Warning(this, "{0}: resistance=0, set to 1000".FormatString(Name));
                        resistance = 1000;
                    }
                }

                var difference = BaseParameters.Temperature - ModelParameters.NominalTemperature;

                if (ModelParameters.ExponentialCoefficient.Given)
                {
                    factor = Math.Pow(1.01, ModelParameters.ExponentialCoefficient * difference);
                }
                else
                {
                    factor = 1.0 + ModelParameters.TemperatureCoefficient1 * difference + ModelParameters.TemperatureCoefficient2 * difference * difference;
                }
            }
            else
            {
                factor = 1.0;
            }

            if (resistance < MinimumResistance)
            {
                resistance = MinimumResistance;
            }

            Conductance = 1.0 / (resistance * factor);
        }
コード例 #6
0
        /// <summary>
        /// Do temperature-dependent calculations
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            if (!BaseParameters.Temperature.Given)
            {
                BaseParameters.Temperature.RawValue = simulation.RealState.Temperature;
            }
            Vt = BaseParameters.Temperature * Constants.KOverQ;
            var fact2 = BaseParameters.Temperature / Constants.ReferenceTemperature;
            var egfet = 1.16 - 7.02e-4 * BaseParameters.Temperature * BaseParameters.Temperature / (BaseParameters.Temperature + 1108);
            var arg   = -egfet / (2 * Constants.Boltzmann * BaseParameters.Temperature) + 1.1150877 / (Constants.Boltzmann * (Constants.ReferenceTemperature +
                                                                                                                              Constants.ReferenceTemperature));
            var pbfact = -2 * Vt * (1.5 * Math.Log(fact2) + Constants.Charge * arg);

            var ratlog  = Math.Log(BaseParameters.Temperature / ModelParameters.NominalTemperature);
            var ratio1  = BaseParameters.Temperature / ModelParameters.NominalTemperature - 1;
            var factlog = ratio1 * ModelParameters.EnergyGap / Vt + ModelParameters.TempExpIs * ratlog;
            var factor  = Math.Exp(factlog);

            TempSaturationCurrent = ModelParameters.SatCur * factor;
            var bfactor = Math.Exp(ratlog * ModelParameters.BetaExponent);

            TempBetaForward      = ModelParameters.BetaF * bfactor;
            TempBetaReverse      = ModelParameters.BetaR * bfactor;
            TempBeLeakageCurrent = ModelParameters.LeakBeCurrent * Math.Exp(factlog / ModelParameters.LeakBeEmissionCoefficient) / bfactor;
            TempBcLeakageCurrent = ModelParameters.LeakBcCurrent * Math.Exp(factlog / ModelParameters.LeakBcEmissionCoefficient) / bfactor;

            var pbo    = (ModelParameters.PotentialBe - pbfact) / ModelTemperature.Factor1;
            var gmaold = (ModelParameters.PotentialBe - pbo) / pbo;

            TempBeCap       = ModelParameters.DepletionCapBe / (1 + ModelParameters.JunctionExpBe * (4e-4 * (ModelParameters.NominalTemperature - Constants.ReferenceTemperature) - gmaold));
            TempBePotential = fact2 * pbo + pbfact;
            var gmanew = (TempBePotential - pbo) / pbo;

            TempBeCap *= 1 + ModelParameters.JunctionExpBe * (4e-4 * (BaseParameters.Temperature - Constants.ReferenceTemperature) - gmanew);

            pbo             = (ModelParameters.PotentialBc - pbfact) / ModelTemperature.Factor1;
            gmaold          = (ModelParameters.PotentialBc - pbo) / pbo;
            TempBcCap       = ModelParameters.DepletionCapBc / (1 + ModelParameters.JunctionExpBc * (4e-4 * (ModelParameters.NominalTemperature - Constants.ReferenceTemperature) - gmaold));
            TempBcPotential = fact2 * pbo + pbfact;
            gmanew          = (TempBcPotential - pbo) / pbo;
            TempBcCap      *= 1 + ModelParameters.JunctionExpBc * (4e-4 * (BaseParameters.Temperature - Constants.ReferenceTemperature) - gmanew);

            TempDepletionCap = ModelParameters.DepletionCapCoefficient * TempBePotential;
            TempFactor1      = TempBePotential * (1 - Math.Exp((1 - ModelParameters.JunctionExpBe) * ModelTemperature.Xfc)) / (1 - ModelParameters.JunctionExpBe);
            TempFactor4      = ModelParameters.DepletionCapCoefficient * TempBcPotential;
            TempFactor5      = TempBcPotential * (1 - Math.Exp((1 - ModelParameters.JunctionExpBc) * ModelTemperature.Xfc)) / (1 - ModelParameters.JunctionExpBc);
            TempVCritical    = Vt * Math.Log(Vt / (Constants.Root2 * ModelParameters.SatCur));
        }
コード例 #7
0
        /// <summary>
        /// Loads the Y-matrix and Rhs-vector.
        /// </summary>
        /// <param name="simulation">The base simulation.</param>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));
            var state = simulation.RealState;

            // Admittance between POS1 and INT1
            Pos1Pos1Ptr.Value += BaseParameters.Admittance;
            Pos1Int1Ptr.Value -= BaseParameters.Admittance;
            Int1Pos1Ptr.Value -= BaseParameters.Admittance;
            Int1Int1Ptr.Value += BaseParameters.Admittance;

            // Admittance between POS2 and INT2
            Pos2Pos2Ptr.Value += BaseParameters.Admittance;
            Pos2Int2Ptr.Value -= BaseParameters.Admittance;
            Int2Pos2Ptr.Value -= BaseParameters.Admittance;
            Int2Int2Ptr.Value += BaseParameters.Admittance;

            // Add the currents to the positive and negative nodes
            Int1Ibr1Ptr.Value += 1.0;
            Neg1Ibr1Ptr.Value -= 1.0;
            Int2Ibr2Ptr.Value += 1.0;
            Neg2Ibr2Ptr.Value -= 1.0;

            if (state.UseDc)
            {
                // Assume DC operation

                // VPOS1 - VNEG1 = VPOS2 - VNEG2
                Ibr1Pos1Ptr.Value += 1.0;
                Ibr1Neg1Ptr.Value -= 1.0;
                Ibr1Pos2Ptr.Value -= 1.0;
                Ibr1Neg2Ptr.Value += 1.0;

                // IBR1 = -IBR2
                Ibr2Ibr1Ptr.Value += 1.0;
                Ibr2Ibr2Ptr.Value += 1.0;
            }
            else
            {
                // INT1-NEG1 voltage source
                Ibr1Int1Ptr.Value += 1.0;
                Ibr1Neg1Ptr.Value -= 1.0;

                // INT2-NEG2 voltage source
                Ibr2Int2Ptr.Value += 1.0;
                Ibr2Neg2Ptr.Value -= 1.0;
            }
        }
コード例 #8
0
ファイル: BiasingBehavior.cs プロジェクト: ewiebe1/SpiceSharp
        /// <summary>
        /// Loads the Y-matrix and Rhs-vector.
        /// </summary>
        /// <param name="simulation">The base simulation.</param>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            PosBranchPtr.Value += 1;
            BranchPosPtr.Value += 1;
            NegBranchPtr.Value -= 1;
            BranchNegPtr.Value -= 1;

            // In DC, the delay should just copy input to output
            if (simulation.RealState.UseDc)
            {
                BranchControlPosPtr.Value -= 1.0;
                BranchControlNegPtr.Value += 1.0;
            }
        }
コード例 #9
0
        /// <summary>
        /// Do temperature-dependent calculations
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public override void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            if (!_mbp.NominalTemperature.Given)
            {
                _mbp.NominalTemperature.RawValue = simulation.RealState.NominalTemperature;
            }
            VtNominal = Constants.KOverQ * _mbp.NominalTemperature;

            // limit grading coeff to max of 0.9
            if (_mbp.GradingCoefficient > 0.9)
            {
                _mbp.GradingCoefficient.RawValue = 0.9;
                CircuitWarning.Warning(this, "{0}: grading coefficient too large, limited to 0.9".FormatString(Name));
            }

            // limit activation energy to min of 0.1
            if (_mbp.ActivationEnergy < 0.1)
            {
                _mbp.ActivationEnergy.RawValue = 0.1;
                CircuitWarning.Warning(this, "{0}: activation energy too small, limited to 0.1".FormatString(Name));
            }

            // limit depletion cap coeff to max of .95
            if (_mbp.DepletionCapCoefficient > 0.95)
            {
                _mbp.DepletionCapCoefficient.RawValue = 0.95;
                CircuitWarning.Warning(this, "{0}: coefficient Fc too large, limited to 0.95".FormatString(Name));
            }

            if (_mbp.Resistance > 0)
            {
                Conductance = 1 / _mbp.Resistance;
            }
            else
            {
                Conductance = 0;
            }
            Xfc = Math.Log(1 - _mbp.DepletionCapCoefficient);

            F2 = Math.Exp((1 + _mbp.GradingCoefficient) * Xfc);
            F3 = 1 - _mbp.DepletionCapCoefficient * (1 + _mbp.GradingCoefficient);
        }
コード例 #10
0
        /// <summary>
        /// Do temperature-dependent calculations
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            if (!BaseParameters.Temperature.Given)
            {
                BaseParameters.Temperature.RawValue = simulation.RealState.Temperature;
            }

            double capacitance;

            if (!BaseParameters.Capacitance.Given)
            {
                if (ModelParameters == null)
                {
                    throw new CircuitException("No model specified");
                }

                var width = BaseParameters.Width.Given
                    ? BaseParameters.Width.Value
                    : ModelParameters.DefaultWidth.Value;
                capacitance = ModelParameters.JunctionCap *
                              (width - ModelParameters.Narrow) *
                              (BaseParameters.Length - ModelParameters.Narrow) +
                              ModelParameters.JunctionCapSidewall * 2 * (
                    BaseParameters.Length - ModelParameters.Narrow +
                    (width - ModelParameters.Narrow));
            }
            else
            {
                capacitance = BaseParameters.Capacitance;
            }

            double factor = 1.0;

            if (ModelParameters != null)
            {
                double temperatureDiff = BaseParameters.Temperature - ModelParameters.NominalTemperature;
                factor = 1.0 + ModelParameters.TemperatureCoefficient1 * temperatureDiff + ModelParameters.TemperatureCoefficient2 * temperatureDiff * temperatureDiff;
            }

            Capacitance = factor * capacitance;
        }
コード例 #11
0
        /// <summary>
        /// Check convergence for the diode
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        /// <returns></returns>
        public bool IsConvergent(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            var state = simulation.RealState;
            var vd    = state.Solution[PosPrimeNode] - state.Solution[NegNode];

            var delvd = vd - Voltage;
            var cdhat = Current + Conductance * delvd;
            var cd    = Current;

            // check convergence
            var tol = BaseConfiguration.RelativeTolerance * Math.Max(Math.Abs(cdhat), Math.Abs(cd)) + BaseConfiguration.AbsoluteTolerance;

            if (Math.Abs(cdhat - cd) > tol)
            {
                state.IsConvergent = false;
                return(false);
            }
            return(true);
        }
コード例 #12
0
ファイル: BiasingBehavior.cs プロジェクト: ewiebe1/SpiceSharp
        /// <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);
            }
        }
コード例 #13
0
        /// <summary>
        /// Perform temperature-dependent calculations.
        /// </summary>
        /// <param name="simulation">The base simulation.</param>
        /// <exception cref="ArgumentNullException">simulation</exception>
        public void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            if (!BaseParameters.Temperature.Given)
            {
                BaseParameters.Temperature.RawValue = simulation.RealState.Temperature;
            }
            var vt     = BaseParameters.Temperature * Constants.KOverQ;
            var fact2  = BaseParameters.Temperature / Constants.ReferenceTemperature;
            var ratio1 = BaseParameters.Temperature / ModelParameters.NominalTemperature - 1;

            TempSaturationCurrent = ModelParameters.GateSaturationCurrent * Math.Exp(ratio1 * 1.11 / vt);
            TempCapGs             = ModelParameters.CapGs * ModelTemperature.Cjfact;
            TempCapGd             = ModelParameters.CapGd * ModelTemperature.Cjfact;
            var kt     = Constants.Boltzmann * BaseParameters.Temperature;
            var egfet  = 1.16 - (7.02e-4 * BaseParameters.Temperature * BaseParameters.Temperature) / (BaseParameters.Temperature + 1108);
            var arg    = -egfet / (kt + kt) + 1.1150877 / (Constants.Boltzmann * 2 * Constants.ReferenceTemperature);
            var pbfact = -2 * vt * (1.5 * Math.Log(fact2) + Constants.Charge * arg);

            TempGatePotential = fact2 * ModelTemperature.Pbo + pbfact;
            var gmanew  = (TempGatePotential - ModelTemperature.Pbo) / ModelTemperature.Pbo;
            var cjfact1 = 1 + .5 * (4e-4 * (BaseParameters.Temperature - Constants.ReferenceTemperature) - gmanew);

            TempCapGs *= cjfact1;
            TempCapGd *= cjfact1;

            CorDepCap = ModelParameters.DepletionCapCoefficient * TempGatePotential;
            F1        = TempGatePotential * (1 - Math.Exp((1 - .5) * ModelTemperature.Xfc)) / (1 - .5);
            Vcrit     = vt * Math.Log(vt / (Constants.Root2 * TempSaturationCurrent));

            if (TempGatePotential.Equals(0.0))
            {
                throw new CircuitException("Invalid parameter " + nameof(TempGatePotential));
            }
        }
コード例 #14
0
ファイル: BiasingBehavior.cs プロジェクト: ewiebe1/SpiceSharp
        /// <summary>
        /// Loads the Y-matrix and Rhs-vector.
        /// </summary>
        /// <param name="simulation">The base simulation.</param>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));
            var state = simulation.RealState;

            // DC model parameters
            var beta = ModelParameters.Beta * BaseParameters.Area;
            var gdpr = ModelParameters.DrainConductance * BaseParameters.Area;
            var gspr = ModelParameters.SourceConductance * BaseParameters.Area;
            var csat = TempSaturationCurrent * BaseParameters.Area;

            double ggs, cg;
            double ggd, cgd;
            double cdrain, gm, gds, betap, bfac;

            // Get the current voltages
            Initialize(simulation, out double vgs, out double vgd, out bool check);
            var vds = vgs - vgd;

            // Determine dc current and derivatives
            if (vgs <= -5 * BaseParameters.Temperature * Constants.KOverQ)
            {
                ggs = -csat / vgs + BaseConfiguration.Gmin;
                cg  = ggs * vgs;
            }
            else
            {
                var evgs = Math.Exp(vgs / (BaseParameters.Temperature * Constants.KOverQ));
                ggs = csat * evgs / (BaseParameters.Temperature * Constants.KOverQ) + BaseConfiguration.Gmin;
                cg  = csat * (evgs - 1) + BaseConfiguration.Gmin * vgs;
            }

            if (vgd <= -5 * (BaseParameters.Temperature * Constants.KOverQ))
            {
                ggd = -csat / vgd + BaseConfiguration.Gmin;
                cgd = ggd * vgd;
            }
            else
            {
                var evgd = Math.Exp(vgd / (BaseParameters.Temperature * Constants.KOverQ));
                ggd = csat * evgd / (BaseParameters.Temperature * Constants.KOverQ) + BaseConfiguration.Gmin;
                cgd = csat * (evgd - 1) + BaseConfiguration.Gmin * vgd;
            }

            cg += cgd;

            // Modification for Sydney University JFET model
            var vto = ModelParameters.Threshold;

            if (vds >= 0)
            {
                var vgst = vgs - vto;

                // Compute drain current and derivatives for normal mode
                if (vgst <= 0)
                {
                    // Normal mode, cutoff region
                    cdrain = 0;
                    gm     = 0;
                    gds    = 0;
                }
                else
                {
                    betap = beta * (1 + ModelParameters.LModulation * vds);
                    bfac  = ModelTemperature.BFactor;
                    if (vgst >= vds)
                    {
                        // Normal mode, linear region
                        var apart = 2 * ModelParameters.B + 3 * bfac * (vgst - vds);
                        var cpart = vds * (vds * (bfac * vds - ModelParameters.B) + vgst * apart);
                        cdrain = betap * cpart;
                        gm     = betap * vds * (apart + 3 * bfac * vgst);
                        gds    = betap * (vgst - vds) * apart
                                 + beta * ModelParameters.LModulation * cpart;
                    }
                    else
                    {
                        bfac = vgst * bfac;
                        gm   = betap * vgst * (2 * ModelParameters.B + 3 * bfac);

                        // Normal mode, saturation region
                        var cpart = vgst * vgst * (ModelParameters.B + bfac);
                        cdrain = betap * cpart;
                        gds    = ModelParameters.LModulation * beta * cpart;
                    }
                }
            }
            else
            {
                var vgdt = vgd - vto;

                // Compute drain current and derivatives for inverse mode
                if (vgdt <= 0)
                {
                    // Inverse mode, cutoff region
                    cdrain = 0;
                    gm     = 0;
                    gds    = 0;
                }
                else
                {
                    betap = beta * (1 - ModelParameters.LModulation * vds);
                    bfac  = ModelTemperature.BFactor;
                    if (vgdt + vds >= 0)
                    {
                        // Inverse mode, linear region
                        var apart = 2 * ModelParameters.B + 3 * bfac * (vgdt + vds);
                        var cpart = vds * (-vds * (-bfac * vds - ModelParameters.B) + vgdt * apart);
                        cdrain = betap * cpart;
                        gm     = betap * vds * (apart + 3 * bfac * vgdt);
                        gds    = betap * (vgdt + vds) * apart
                                 - beta * ModelParameters.LModulation * cpart - gm;
                    }
                    else
                    {
                        bfac = vgdt * bfac;
                        gm   = -betap * vgdt * (2 * ModelParameters.B + 3 * bfac);

                        // Inverse mode, saturation region
                        var cpart = vgdt * vgdt * (ModelParameters.B + bfac);
                        cdrain = -betap * cpart;
                        gds    = ModelParameters.LModulation * beta * cpart - gm;
                    }
                }
            }

            var cd = cdrain - cgd;

            Vgs = vgs;
            Vgd = vgd;
            Cg  = cg;
            Cd  = cd;
            Cgd = cgd;
            Gm  = gm;
            Gds = gds;
            Ggs = ggs;
            Ggd = ggd;

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

            // Load current vector
            var ceqgd = ModelParameters.JFETType * (cgd - ggd * vgd);
            var ceqgs = ModelParameters.JFETType * (cg - cgd - ggs * vgs);
            var cdreq = ModelParameters.JFETType * (cd + cgd - gds * vds - gm * vgs);

            GateNodePtr.Value        += -ceqgs - ceqgd;
            DrainPrimeNodePtr.Value  += -cdreq + ceqgd;
            SourcePrimeNodePtr.Value += cdreq + ceqgs;

            // Load Y-matrix
            DrainDrainPrimePtr.Value       += -gdpr;
            GateDrainPrimePtr.Value        += -ggd;
            GateSourcePrimePtr.Value       += -ggs;
            SourceSourcePrimePtr.Value     += -gspr;
            DrainPrimeDrainPtr.Value       += -gdpr;
            DrainPrimeGatePtr.Value        += gm - ggd;
            DrainPrimeSourcePrimePtr.Value += -gds - gm;
            SourcePrimeGatePtr.Value       += -ggs - gm;
            SourcePrimeSourcePtr.Value     += -gspr;
            SourcePrimeDrainPrimePtr.Value += -gds;
            DrainDrainPtr.Value            += gdpr;
            GateGatePtr.Value               += ggd + ggs;
            SourceSourcePtr.Value           += gspr;
            DrainPrimeDrainPrimePtr.Value   += gdpr + gds + ggd;
            SourcePrimeSourcePrimePtr.Value += gspr + gds + gm + ggs;
        }
コード例 #15
0
        /// <summary>
        /// Do temperature-dependent calculations
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            // Perform model defaulting
            if (!ModelParameters.NominalTemperature.Given)
            {
                ModelParameters.NominalTemperature.RawValue = simulation.RealState.NominalTemperature;
            }
            Factor1   = ModelParameters.NominalTemperature / Constants.ReferenceTemperature;
            VtNominal = ModelParameters.NominalTemperature * Constants.KOverQ;
            var kt1 = Constants.Boltzmann * ModelParameters.NominalTemperature;

            EgFet1 = 1.16 - 7.02e-4 * ModelParameters.NominalTemperature * ModelParameters.NominalTemperature / (ModelParameters.NominalTemperature + 1108);
            var arg1 = -EgFet1 / (kt1 + kt1) + 1.1150877 / (Constants.Boltzmann * (Constants.ReferenceTemperature + Constants.ReferenceTemperature));

            PbFactor1 = -2 * VtNominal * (1.5 * Math.Log(Factor1) + Constants.Charge * arg1);

            if (ModelParameters.SubstrateDoping.Given)
            {
                if (ModelParameters.SubstrateDoping * 1e6 > 1.45e16)
                {
                    if (!ModelParameters.Phi.Given)
                    {
                        ModelParameters.Phi.RawValue = 2 * VtNominal * Math.Log(ModelParameters.SubstrateDoping * 1e6 / 1.45e16);
                        ModelParameters.Phi.RawValue = Math.Max(.1, ModelParameters.Phi);
                    }
                    var fermis = ModelParameters.MosfetType * .5 * ModelParameters.Phi;
                    var wkfng  = 3.2;
                    if (!ModelParameters.GateType.Given)
                    {
                        ModelParameters.GateType.RawValue = 1;
                    }
                    if (!ModelParameters.GateType.RawValue.Equals(0))
                    {
                        var fermig = ModelParameters.MosfetType * ModelParameters.GateType * .5 * EgFet1;
                        wkfng = 3.25 + .5 * EgFet1 - fermig;
                    }
                    var wkfngs = wkfng - (3.25 + .5 * EgFet1 + fermis);
                    if (!ModelParameters.Gamma.Given)
                    {
                        ModelParameters.Gamma.RawValue = Math.Sqrt(2 * 11.70 * 8.854214871e-12 * Constants.Charge * ModelParameters.SubstrateDoping * 1e6) / ModelParameters.OxideCapFactor;
                    }
                    if (!ModelParameters.Vt0.Given)
                    {
                        if (!ModelParameters.SurfaceStateDensity.Given)
                        {
                            ModelParameters.SurfaceStateDensity.RawValue = 0;
                        }
                        var vfb = wkfngs - ModelParameters.SurfaceStateDensity * 1e4 * Constants.Charge / ModelParameters.OxideCapFactor;
                        ModelParameters.Vt0.RawValue = vfb + ModelParameters.MosfetType * (ModelParameters.Gamma * Math.Sqrt(ModelParameters.Phi) + ModelParameters.Phi);
                    }

                    Xd = Math.Sqrt((EpsilonSilicon + EpsilonSilicon) / (Constants.Charge * ModelParameters.SubstrateDoping * 1e6));
                }
                else
                {
                    ModelParameters.SubstrateDoping.RawValue = 0;
                    throw new CircuitException("{0}: Nsub < Ni".FormatString(Name));
                }
            }
            if (!ModelParameters.BulkCapFactor.Given)
            {
                ModelParameters.BulkCapFactor.RawValue = Math.Sqrt(EpsilonSilicon * Constants.Charge * ModelParameters.SubstrateDoping * 1e6 /* cm**3/m**3 */ / (2 *
                                                                                                                                                                 ModelParameters.BulkJunctionPotential));
            }
        }
コード例 #16
0
ファイル: BiasingBehavior.cs プロジェクト: ewiebe1/SpiceSharp
        /// <summary>
        /// Loads the Y-matrix and Rhs-vector.
        /// </summary>
        /// <param name="simulation">The base simulation.</param>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));
            var state = simulation.RealState;

            // Get the current voltages
            Initialize(simulation, out double vgs, out var vds, out var vbs, out var check);
            var vbd = vbs - vds;
            var vgd = vgs - vds;

            /*
             * bulk-source and bulk-drain diodes
             * here we just evaluate the ideal diode current and the
             * corresponding derivative (conductance).
             */
            if (vbs <= 0)
            {
                CondBs    = SourceSatCurrent / Vt;
                BsCurrent = CondBs * vbs;
                CondBs   += BaseConfiguration.Gmin;
            }
            else
            {
                var evbs = Math.Exp(Math.Min(MaximumExponentArgument, vbs / Vt));
                CondBs    = SourceSatCurrent * evbs / Vt + BaseConfiguration.Gmin;
                BsCurrent = SourceSatCurrent * (evbs - 1);
            }
            if (vbd <= 0)
            {
                CondBd    = DrainSatCurrent / Vt;
                BdCurrent = CondBd * vbd;
                CondBd   += BaseConfiguration.Gmin;
            }
            else
            {
                var evbd = Math.Exp(Math.Min(MaximumExponentArgument, vbd / Vt));
                CondBd    = DrainSatCurrent * evbd / Vt + BaseConfiguration.Gmin;
                BdCurrent = DrainSatCurrent * (evbd - 1);
            }

            /*
             * Now to determine whether the user was able to correctly
             * identify the source and drain of his device
             */
            if (vds >= 0)
            {
                // normal mode
                Mode = 1;
            }
            else
            {
                // inverse mode
                Mode = -1;
            }

            // Update
            VoltageBs = vbs;
            VoltageBd = vbd;
            VoltageGs = vgs;
            VoltageDs = vds;

            // Evaluate the currents and derivatives
            var cdrain = Mode > 0 ? Evaluate(vgs, vds, vbs) : Evaluate(vgd, -vds, vbd);

            DrainCurrent = Mode * cdrain - BdCurrent;

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

            // Load current vector
            double xnrm, xrev, cdreq;
            var    ceqbs = ModelParameters.MosfetType * (BsCurrent - (CondBs - BaseConfiguration.Gmin) * vbs);
            var    ceqbd = ModelParameters.MosfetType * (BdCurrent - (CondBd - BaseConfiguration.Gmin) * vbd);

            if (Mode >= 0)
            {
                xnrm  = 1;
                xrev  = 0;
                cdreq = ModelParameters.MosfetType * (cdrain - CondDs * vds - Transconductance * vgs - TransconductanceBs * vbs);
            }
            else
            {
                xnrm  = 0;
                xrev  = 1;
                cdreq = -ModelParameters.MosfetType * (cdrain - CondDs * -vds - Transconductance * vgd - TransconductanceBs * vbd);
            }
            BulkPtr.Value        -= ceqbs + ceqbd;
            DrainPrimePtr.Value  += ceqbd - cdreq;
            SourcePrimePtr.Value += cdreq + ceqbs;

            // Load Y-matrix
            DrainDrainPtr.Value             += DrainConductance;
            SourceSourcePtr.Value           += SourceConductance;
            BulkBulkPtr.Value               += CondBd + CondBs;
            DrainPrimeDrainPrimePtr.Value   += DrainConductance + CondDs + CondBd + xrev * (Transconductance + TransconductanceBs);
            SourcePrimeSourcePrimePtr.Value += SourceConductance + CondDs + CondBs + xnrm * (Transconductance + TransconductanceBs);
            DrainDrainPrimePtr.Value        += -DrainConductance;
            SourceSourcePrimePtr.Value      += -SourceConductance;
            BulkDrainPrimePtr.Value         -= CondBd;
            BulkSourcePrimePtr.Value        -= CondBs;
            DrainPrimeDrainPtr.Value        += -DrainConductance;
            DrainPrimeGatePtr.Value         += (xnrm - xrev) * Transconductance;
            DrainPrimeBulkPtr.Value         += -CondBd + (xnrm - xrev) * TransconductanceBs;
            DrainPrimeSourcePrimePtr.Value  += -CondDs - xnrm * (Transconductance + TransconductanceBs);
            SourcePrimeGatePtr.Value        += -(xnrm - xrev) * Transconductance;
            SourcePrimeSourcePtr.Value      += -SourceConductance;
            SourcePrimeBulkPtr.Value        += -CondBs - (xnrm - xrev) * TransconductanceBs;
            SourcePrimeDrainPrimePtr.Value  += -CondDs - xrev * (Transconductance + TransconductanceBs);
        }
コード例 #17
0
        /// <summary>
        /// Do temperature-dependent calculations
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public override void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            if (!_mbp.NominalTemperature.Given)
            {
                _mbp.NominalTemperature.RawValue = simulation.RealState.NominalTemperature;
            }
            Factor1 = _mbp.NominalTemperature / Constants.ReferenceTemperature;

            if (!_mbp.LeakBeCurrent.Given)
            {
                if (_mbp.C2.Given)
                {
                    _mbp.LeakBeCurrent.RawValue = _mbp.C2 * _mbp.SatCur;
                }
                else
                {
                    _mbp.LeakBeCurrent.RawValue = 0;
                }
            }
            if (!_mbp.LeakBcCurrent.Given)
            {
                if (_mbp.C4.Given)
                {
                    _mbp.LeakBcCurrent.RawValue = _mbp.C4 * _mbp.SatCur;
                }
                else
                {
                    _mbp.LeakBcCurrent.RawValue = 0;
                }
            }
            if (!_mbp.MinimumBaseResistance.Given)
            {
                _mbp.MinimumBaseResistance.RawValue = _mbp.BaseResist;
            }

            /*
             * COMPATABILITY WARNING!
             * special note: for backward compatability to much older models, spice 2G
             * implemented a special case which checked if B-E leakage saturation
             * current was >1, then it was instead a the B-E leakage saturation current
             * divided by IS, and multiplied it by IS at this point. This was not
             * handled correctly in the 2G code, and there is some question on its
             * reasonability, since it is also undocumented, so it has been left out
             * here. It could easily be added with 1 line. (The same applies to the B-C
             * leakage saturation current).   TQ  6/29/84
             */

            if (_mbp.EarlyVoltageForward.Given && !_mbp.EarlyVoltageForward.Value.Equals(0.0))
            {
                InverseEarlyVoltForward = 1 / _mbp.EarlyVoltageForward;
            }
            else
            {
                InverseEarlyVoltForward = 0;
            }
            if (_mbp.RollOffForward.Given && !_mbp.RollOffForward.Value.Equals(0.0))
            {
                InverseRollOffForward = 1 / _mbp.RollOffForward;
            }
            else
            {
                InverseRollOffForward = 0;
            }
            if (_mbp.EarlyVoltageReverse.Given && !_mbp.EarlyVoltageReverse.Value.Equals(0.0))
            {
                InverseEarlyVoltReverse = 1 / _mbp.EarlyVoltageReverse;
            }
            else
            {
                InverseEarlyVoltReverse = 0;
            }
            if (_mbp.RollOffReverse.Given && !_mbp.RollOffReverse.Value.Equals(0.0))
            {
                InverseRollOffReverse = 1 / _mbp.RollOffReverse;
            }
            else
            {
                InverseRollOffReverse = 0;
            }
            if (_mbp.CollectorResistance.Given && !_mbp.CollectorResistance.Value.Equals(0.0))
            {
                CollectorConduct = 1 / _mbp.CollectorResistance;
            }
            else
            {
                CollectorConduct = 0;
            }
            if (_mbp.EmitterResistance.Given && !_mbp.EmitterResistance.Value.Equals(0.0))
            {
                EmitterConduct = 1 / _mbp.EmitterResistance;
            }
            else
            {
                EmitterConduct = 0;
            }
            if (_mbp.TransitTimeForwardVoltageBc.Given && !_mbp.TransitTimeForwardVoltageBc.Value.Equals(0.0))
            {
                TransitTimeVoltageBcFactor = 1 / (_mbp.TransitTimeForwardVoltageBc * 1.44);
            }
            else
            {
                TransitTimeVoltageBcFactor = 0;
            }
            ExcessPhaseFactor = _mbp.ExcessPhase / (180.0 / Math.PI) * _mbp.TransitTimeForward;
            if (_mbp.DepletionCapCoefficient.Given)
            {
                if (_mbp.DepletionCapCoefficient > 0.9999)
                {
                    _mbp.DepletionCapCoefficient.RawValue = 0.9999;
                    throw new CircuitException("BJT model {0}, parameter fc limited to 0.9999".FormatString(Name));
                }
            }
            else
            {
                _mbp.DepletionCapCoefficient.RawValue = 0.5;
            }
            Xfc = Math.Log(1 - _mbp.DepletionCapCoefficient);
            F2  = Math.Exp((1 + _mbp.JunctionExpBe) * Xfc);
            F3  = 1 - _mbp.DepletionCapCoefficient * (1 + _mbp.JunctionExpBe);
            F6  = Math.Exp((1 + _mbp.JunctionExpBc) * Xfc);
            F7  = 1 - _mbp.DepletionCapCoefficient * (1 + _mbp.JunctionExpBc);
        }
コード例 #18
0
ファイル: BiasingBehavior.cs プロジェクト: ewiebe1/SpiceSharp
        /// <summary>
        /// Loads the Y-matrix and Rhs-vector.
        /// </summary>
        /// <param name="simulation">The base simulation.</param>
        /// <exception cref="NotImplementedException"></exception>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            bool currentState;
            var  state = simulation.RealState;

            // decide the state of the switch
            if (state.Init == InitializationModes.Fix || state.Init == InitializationModes.Junction)
            {
                if (BaseParameters.ZeroState)
                {
                    // Switch specified "on"
                    CurrentState = true;
                    currentState = true;
                }
                else
                {
                    // Switch specified "off"
                    CurrentState = false;
                    currentState = false;
                }
            }
            else
            {
                // Get the previous state
                var ctrl = Method.GetValue(state);
                if (UseOldState)
                {
                    // Calculate the current state
                    if (ctrl > ModelParameters.Threshold + ModelParameters.Hysteresis)
                    {
                        currentState = true;
                    }
                    else if (ctrl < ModelParameters.Threshold - ModelParameters.Hysteresis)
                    {
                        currentState = false;
                    }
                    else
                    {
                        currentState = PreviousState;
                    }
                    CurrentState = currentState;
                    UseOldState  = false;
                }
                else
                {
                    PreviousState = CurrentState;

                    // Calculate the current state
                    if (ctrl > ModelParameters.Threshold + ModelParameters.Hysteresis)
                    {
                        CurrentState = true;
                        currentState = true;
                    }
                    else if (ctrl < ModelParameters.Threshold - ModelParameters.Hysteresis)
                    {
                        CurrentState = false;
                        currentState = false;
                    }
                    else
                    {
                        currentState = PreviousState;
                    }

                    // Ensure one more iteration
                    if (currentState != PreviousState)
                    {
                        state.IsConvergent = false;
                    }
                }

                // Store the current state
                CurrentState = currentState;

                // If the state changed, ensure one more iteration
                if (currentState != PreviousState)
                {
                    state.IsConvergent = false;
                }
            }

            // Get the current conduction
            var gNow = currentState ? ModelParameters.OnConductance : ModelParameters.OffConductance;

            Conductance = gNow;

            // Load the Y-matrix
            PosPosPtr.Value += gNow;
            PosNegPtr.Value -= gNow;
            NegPosPtr.Value -= gNow;
            NegNegPtr.Value += gNow;
        }
コード例 #19
0
        /// <summary>
        /// Do temperature-dependent calculations
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Temperature(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            var xcbv = 0.0;

            // loop through all the instances
            if (!BaseParameters.Temperature.Given)
            {
                BaseParameters.Temperature.RawValue = simulation.RealState.Temperature;
            }
            Vt  = Constants.KOverQ * BaseParameters.Temperature;
            Vte = ModelParameters.EmissionCoefficient * Vt;

            // this part gets really ugly - I won't even try to explain these equations
            var fact2 = BaseParameters.Temperature / Constants.ReferenceTemperature;
            var egfet = 1.16 - 7.02e-4 * BaseParameters.Temperature * BaseParameters.Temperature / (BaseParameters.Temperature + 1108);
            var arg   = -egfet / (2 * Constants.Boltzmann * BaseParameters.Temperature) + 1.1150877 / (Constants.Boltzmann * (Constants.ReferenceTemperature +
                                                                                                                              Constants.ReferenceTemperature));
            var pbfact  = -2 * Vt * (1.5 * Math.Log(fact2) + Constants.Charge * arg);
            var egfet1  = 1.16 - 7.02e-4 * ModelParameters.NominalTemperature * ModelParameters.NominalTemperature / (ModelParameters.NominalTemperature + 1108);
            var arg1    = -egfet1 / (Constants.Boltzmann * 2 * ModelParameters.NominalTemperature) + 1.1150877 / (2 * Constants.Boltzmann * Constants.ReferenceTemperature);
            var fact1   = ModelParameters.NominalTemperature / Constants.ReferenceTemperature;
            var pbfact1 = -2 * ModelTemperature.VtNominal * (1.5 * Math.Log(fact1) + Constants.Charge * arg1);
            var pbo     = (ModelParameters.JunctionPotential - pbfact1) / fact1;
            var gmaold  = (ModelParameters.JunctionPotential - pbo) / pbo;

            TempJunctionCap = ModelParameters.JunctionCap / (1 + ModelParameters.GradingCoefficient * (400e-6 * (ModelParameters.NominalTemperature - Constants.ReferenceTemperature) - gmaold));
            TempJunctionPot = pbfact + fact2 * pbo;
            var gmanew = (TempJunctionPot - pbo) / pbo;

            TempJunctionCap *= 1 + ModelParameters.GradingCoefficient * (400e-6 * (BaseParameters.Temperature - Constants.ReferenceTemperature) - gmanew);

            TempSaturationCurrent = ModelParameters.SaturationCurrent * Math.Exp((BaseParameters.Temperature / ModelParameters.NominalTemperature - 1) * ModelParameters.ActivationEnergy /
                                                                                 (ModelParameters.EmissionCoefficient * Vt) + ModelParameters.SaturationCurrentExp / ModelParameters.EmissionCoefficient * Math.Log(BaseParameters.Temperature / ModelParameters.NominalTemperature));

            // the defintion of f1, just recompute after temperature adjusting all the variables used in it
            TempFactor1 = TempJunctionPot * (1 - Math.Exp((1 - ModelParameters.GradingCoefficient) * ModelTemperature.Xfc)) / (1 - ModelParameters.GradingCoefficient);

            // same for Depletion Capacitance
            TempDepletionCap = ModelParameters.DepletionCapCoefficient * TempJunctionPot;

            // and Vcrit
            var vte = ModelParameters.EmissionCoefficient * Vt;

            TempVCritical = vte * Math.Log(vte / (Constants.Root2 * TempSaturationCurrent));

            // and now to copute the breakdown voltage, again, using temperature adjusted basic parameters
            if (ModelParameters.BreakdownVoltage.Given)
            {
                double cbv = ModelParameters.BreakdownCurrent;
                double xbv;
                if (cbv < TempSaturationCurrent * ModelParameters.BreakdownVoltage / Vt)
                {
                    cbv = TempSaturationCurrent * ModelParameters.BreakdownVoltage / Vt;
                    CircuitWarning.Warning(this, "{0}: breakdown current increased to {1:g} to resolve incompatability with specified saturation current".FormatString(Name, cbv));
                    xbv = ModelParameters.BreakdownVoltage;
                }
                else
                {
                    var tol = BaseConfiguration.RelativeTolerance * cbv;
                    xbv = ModelParameters.BreakdownVoltage - Vt * Math.Log(1 + cbv / TempSaturationCurrent);
                    int iter;
                    for (iter = 0; iter < 25; iter++)
                    {
                        xbv  = ModelParameters.BreakdownVoltage - Vt * Math.Log(cbv / TempSaturationCurrent + 1 - xbv / Vt);
                        xcbv = TempSaturationCurrent * (Math.Exp((ModelParameters.BreakdownVoltage - xbv) / Vt) - 1 + xbv / Vt);
                        if (Math.Abs(xcbv - cbv) <= tol)
                        {
                            break;
                        }
                    }
                    if (iter >= 25)
                    {
                        CircuitWarning.Warning(this, "{0}: unable to match forward and reverse diode regions: bv = {1:g}, ibv = {2:g}".FormatString(Name, xbv, xcbv));
                    }
                }
                TempBreakdownVoltage = xbv;
            }
        }
コード例 #20
0
        /// <summary>
        /// Execute behavior
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            var    state = simulation.RealState;
            double cd, gd;

            // Get the current voltages
            Initialize(simulation, out double vd, out bool check);

            /*
             * this routine loads diodes for dc and transient analyses.
             */
            var csat = TempSaturationCurrent * BaseParameters.Area;
            var gspr = ModelTemperature.Conductance * BaseParameters.Area;

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

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

            // Store for next time
            Voltage     = vd;
            Current     = cd;
            Conductance = 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;
        }
コード例 #21
0
ファイル: BiasingBehavior.cs プロジェクト: ewiebe1/SpiceSharp
        /// <summary>
        /// Execute behavior
        /// </summary>
        /// <param name="simulation">Base simulation</param>
        public void Load(BaseSimulation simulation)
        {
            simulation.ThrowIfNull(nameof(simulation));

            double gben;
            double cben;
            double gbcn;
            double cbcn;

            // DC model parameters
            var csat = TempSaturationCurrent * BaseParameters.Area;
            var rbpr = ModelParameters.MinimumBaseResistance / BaseParameters.Area;
            var rbpi = ModelParameters.BaseResist / BaseParameters.Area - rbpr;
            var gcpr = ModelTemperature.CollectorConduct * BaseParameters.Area;
            var gepr = ModelTemperature.EmitterConduct * BaseParameters.Area;
            var oik  = ModelTemperature.InverseRollOffForward / BaseParameters.Area;
            var c2   = TempBeLeakageCurrent * BaseParameters.Area;
            var vte  = ModelParameters.LeakBeEmissionCoefficient * Vt;
            var oikr = ModelTemperature.InverseRollOffReverse / BaseParameters.Area;
            var c4   = TempBcLeakageCurrent * BaseParameters.Area;
            var vtc  = ModelParameters.LeakBcEmissionCoefficient * Vt;
            var xjrb = ModelParameters.BaseCurrentHalfResist * BaseParameters.Area;

            // Get the current voltages
            Initialize(simulation, out var vbe, out var vbc);

            // Determine dc current and derivitives
            var vtn = Vt * ModelParameters.EmissionCoefficientForward;

            if (vbe > -5 * vtn)
            {
                var evbe = Math.Exp(vbe / vtn);
                CurrentBe = csat * (evbe - 1) + BaseConfiguration.Gmin * vbe;
                CondBe    = csat * evbe / vtn + BaseConfiguration.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 + BaseConfiguration.Gmin;
                CurrentBe = CondBe * vbe;
                gben      = -c2 / vbe;
                cben      = gben * vbe;
            }

            vtn = Vt * ModelParameters.EmissionCoefficientReverse;
            if (vbc > -5 * vtn)
            {
                var evbc = Math.Exp(vbc / vtn);
                CurrentBc = csat * (evbc - 1) + BaseConfiguration.Gmin * vbc;
                CondBc    = csat * evbc / vtn + BaseConfiguration.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 + BaseConfiguration.Gmin;
                CurrentBc = CondBc * vbc;
                gbcn      = -c4 / vbc;
                cbcn      = gbcn * vbc;
            }

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

            if (oik.Equals(0) && oikr.Equals(0)) // Avoid computations
            {
                BaseCharge = q1;
                Dqbdve     = q1 * BaseCharge * ModelTemperature.InverseEarlyVoltReverse;
                Dqbdvc     = q1 * BaseCharge * ModelTemperature.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 * ModelTemperature.InverseEarlyVoltReverse + oik * CondBe / sqarg);
                Dqbdvc     = q1 * (BaseCharge * ModelTemperature.InverseEarlyVoltForward + oikr * CondBc / sqarg);
            }

            // Excess phase calculation
            var cc  = 0.0;
            var cex = CurrentBe;
            var gex = CondBe;

            ExcessPhaseCalculation(ref cc, ref cex, ref gex);

            // Determine dc incremental conductances
            cc = cc + (cex - CurrentBc) / BaseCharge - CurrentBc / TempBetaReverse - cbcn;
            var cb = CurrentBe / TempBetaForward + cben + CurrentBc / 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 / TempBetaForward + gben;
            var gmu = CondBc / 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 = ModelParameters.BipolarType * (cc + cb - vbe * (gm + go + gpi) + vbc * go);
            var ceqbc = ModelParameters.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;
        }