示例#1
0
        /// <inheritdoc/>
        protected override void CreateBehaviors(IEntityCollection entities)
        {
            base.CreateBehaviors(entities);
            _temperatureBehaviors = EntityBehaviors.GetBehaviorList <ITemperatureBehavior>();
            _loadBehaviors        = EntityBehaviors.GetBehaviorList <IBiasingBehavior>();
            _convergenceBehaviors = EntityBehaviors.GetBehaviorList <IConvergenceBehavior>();
            _updateBehaviors      = EntityBehaviors.GetBehaviorList <IBiasingUpdateBehavior>();

            // We're going to set up our state now that all behaviors have allocated elements in the solver
            _state.Setup();

            // Set up nodesets for nodes that were referenced by an entity
            _nodesets.Clear();
            foreach (var ns in BiasingParameters.Nodesets)
            {
                if (_state.TryGetValue(ns.Key, out var variable))
                {
                    _nodesets.Add(new ConvergenceAid(variable, _state, ns.Value));
                }
                else
                {
                    SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_ConvergenceAidVariableNotFound.FormatString(ns.Key));
                }
            }
        }
示例#2
0
        /// <summary>
        /// Iterates to a solution slowly ramping up independent voltages and currents.
        /// </summary>
        /// <param name="maxIterations">The maximum number of iterations per step.</param>
        /// <param name="steps">The number of steps.</param>
        /// <returns>
        /// <c>true</c> if source stepping succeeded; otherwise <c>false</c>.
        /// </returns>
        protected bool IterateSourceStepping(int maxIterations, int steps)
        {
            // We will slowly ramp up voltages starting at 0 to make sure it converges
            SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_Biasing_StartSourceStepping);

            // We could've ended up with some crazy value, so let's reset it
            for (var i = 0; i <= _state.Solution.Length; i++)
            {
                _state.Solution[i] = 0.0;
            }

            // Start SRC stepping
            bool success = true;

            Iteration.Mode = IterationModes.Junction;
            for (var i = 0; i <= steps; i++)
            {
                Iteration.SourceFactor = i / (double)steps;
                if (!Iterate(maxIterations))
                {
                    Iteration.SourceFactor = 1.0;
                    SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_Biasing_SourceSteppingFailed);
                    success = false;
                    break;
                }
            }

            return(success);
        }
示例#3
0
        /// <inheritdoc/>
        void ITemperatureBehavior.Temperature()
        {
            double factor;
            double resistance = Parameters.Resistance;

            // Default Value Processing for Resistor Instance
            if (!Parameters.Temperature.Given)
            {
                Parameters.Temperature = new GivenParameter <double>(_temperature.Temperature, false);
            }

            if (_mbp != null)
            {
                if (!Parameters.Resistance.Given)
                {
                    if (!Parameters.Width.Given)
                    {
                        Parameters.Width = new GivenParameter <double>(_mbp.DefaultWidth, false);
                    }

                    if (!_mbp.SheetResistance.Equals(0.0) && Parameters.Length > 0)
                    {
                        resistance = _mbp.SheetResistance * (Parameters.Length - _mbp.Narrow) / (Parameters.Width - _mbp.Narrow);
                    }
                    else
                    {
                        SpiceSharpWarning.Warning(this, Properties.Resources.Resistors_ZeroResistance.FormatString(Name));
                        resistance = 1000;
                    }
                }

                var difference = Parameters.Temperature - _mbp.NominalTemperature;

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

            if (resistance < Parameters.MinimumResistance)
            {
                SpiceSharpWarning.Warning(this, Properties.Resources.Parameters_NotGreaterOrEqual.FormatString("resistance", resistance, Parameters.MinimumResistance));
                resistance = Parameters.MinimumResistance;
            }

            // Calculate the final conductance
            Conductance = Parameters.ParallelMultiplier / Parameters.SeriesMultiplier / (resistance * factor);
        }
        /// <inheritdoc/>
        public override int OrderAndFactor()
        {
            IsFactored = false;
            int step  = 1;
            var order = Size - Degeneracy;
            int max   = Size - PivotSearchReduction;

            if (!NeedsReordering)
            {
                // Matrix has been factored before, and reordering is not required
                for (step = 1; step <= order; step++)
                {
                    var pivot = Matrix.FindDiagonalElement(step);
                    if (Parameters.IsValidPivot(pivot, max))
                    {
                        Eliminate(pivot);
                    }
                    else
                    {
                        NeedsReordering = true;
                        break;
                    }
                }

                if (!NeedsReordering)
                {
                    IsFactored = true;
                    return(order);
                }
            }

            // Setup the strategy for some real kick-ass pivoting action
            Parameters.Setup(Matrix, Vector, step, max);

            for (; step <= order; step++)
            {
                var pivot = Parameters.FindPivot(Matrix, step, max);
                if (pivot.Info == PivotInfo.None)
                {
                    return(step - 1);
                }
                else if (pivot.Info == PivotInfo.Bad)
                {
                    var loc = InternalToExternal(new MatrixLocation(step, step));
                    SpiceSharpWarning.Warning(this, Properties.Resources.Algebra_BadlyConditioned.FormatString(loc.Row, loc.Column));
                }
                MovePivot(pivot.Element, step);
                Eliminate(pivot.Element);
            }

            IsFactored      = true;
            NeedsReordering = false;
            return(order);
        }
示例#5
0
        /// <summary>
        /// Set up the simulation.
        /// </summary>
        /// <param name="entities">The entities that are included in the simulation.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="entities"/> is <c>null</c>.</exception>
        private void Setup(IEntityCollection entities)
        {
            // Validate the entities
            entities.ThrowIfNull(nameof(entities));
            if (entities.Count == 0)
            {
                // No entities! Don't stop here, but at least warn the user.
                SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_NoEntities.FormatString(Name));
            }

            // Create all simulation states
            CreateStates();

            // Create all entity behaviors (using the created simulation states)
            CreateBehaviors(entities);
        }
示例#6
0
        /// <summary>
        /// Iterates to a solution while adding a conductive path to ground on all nodes.
        /// </summary>
        /// <param name="maxIterations">The maximum number of iterations per step.</param>
        /// <param name="steps">The number of steps.</param>
        /// <returns>
        /// <c>true</c> if the diagonal gmin stepping succeeded; otherwise <c>false</c>.
        /// </returns>
        protected bool IterateDiagonalGminStepping(int maxIterations, int steps)
        {
            // We will add a DC path to ground to all nodes to aid convergence
            SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_Biasing_StartDiagonalGminStepping);

            // We'll hack into the loading algorithm to apply our diagonal contributions
            var diagonalGmin = Math.Min(Iteration.Gmin, 1e-12);

            void ApplyGminStep(object sender, LoadStateEventArgs args)
            => _state.Solver.Precondition((matrix, vector) => ModifiedNodalAnalysisHelper <double> .ApplyDiagonalGmin(matrix, diagonalGmin));

            AfterLoad += ApplyGminStep;

            // We could've ended up with some crazy value, so let's reset it
            for (var i = 0; i <= _state.Solution.Length; i++)
            {
                _state.Solution[i] = 0.0;
            }

            // Let's make it a bit easier for our iterations to converge
            for (var i = 0; i < steps; i++)
            {
                diagonalGmin *= 10.0;
            }

            // Start GMIN stepping
            Iteration.Mode = IterationModes.Junction;
            for (var i = 0; i <= steps; i++)
            {
                Iteration.IsConvergent = false;
                if (!Iterate(maxIterations))
                {
                    diagonalGmin = 0.0;
                    SpiceSharpWarning.Warning(this, Properties.Resources.Simulation_Biasing_GminSteppingFailed);
                    break;
                }
                diagonalGmin  /= 10.0;
                Iteration.Mode = IterationModes.Float;
            }

            // Try one more time without the gmin stepping
            AfterLoad   -= ApplyGminStep;
            diagonalGmin = 0.0;
            return(Iterate(maxIterations));
        }
示例#7
0
        /// <summary>
        /// Iterates to a solution while shunting PN-junctions with a conductance.
        /// </summary>
        /// <param name="maxIterations">The maximum number of iterations per step.</param>
        /// <param name="steps">The number of steps.</param>
        /// <returns>
        /// <c>true</c> if the gmin stepping succeeded; otherwise <c>false</c>.
        /// </returns>
        protected bool IterateGminStepping(int maxIterations, int steps)
        {
            // We will shunt all PN-junctions with a conductance (should be implemented by the components)
            SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_Biasing_StartGminStepping);

            // We could've ended up with some crazy value, so let's reset it
            for (var i = 0; i <= _state.Solution.Length; i++)
            {
                _state.Solution[i] = 0.0;
            }

            // Let's make it a bit easier for our iterations to converge
            var original = Iteration.Gmin;

            if (Iteration.Gmin <= 0)
            {
                Iteration.Gmin = 1e-12;
            }
            for (var i = 0; i < steps; i++)
            {
                Iteration.Gmin *= 10.0;
            }

            // Start GMIN stepping
            Iteration.Mode = IterationModes.Junction;
            for (var i = 0; i <= steps; i++)
            {
                Iteration.IsConvergent = false;
                if (!Iterate(maxIterations))
                {
                    Iteration.Gmin = original;
                    SpiceSharpWarning.Warning(this, Properties.Resources.Simulation_Biasing_GminSteppingFailed);
                    break;
                }

                // Success! Let's try to get more accurate now
                Iteration.Gmin /= 10.0;
                Iteration.Mode  = IterationModes.Float;
            }

            // Try one more time with the original gmin
            Iteration.Gmin = original;
            return(Iterate(maxIterations));
        }
示例#8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BiasingBehavior"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="context"/> is <c>null</c>.</exception>
        public BiasingBehavior(IComponentBindingContext context)
            : base(context)
        {
            context.ThrowIfNull(nameof(context));

            Parameters = context.GetParameterSet <IndependentSourceParameters>();
            _iteration = context.GetState <IIterationSimulationState>();
            context.TryGetState(out _method);
            Waveform = Parameters.Waveform?.Create(_method);
            if (!Parameters.DcValue.Given)
            {
                // No DC value: either have a transient value or none
                if (Waveform != null)
                {
                    SpiceSharpWarning.Warning(this,
                                              Properties.Resources.IndependentSources_NoDcUseWaveform.FormatString(Name));
                    Parameters.DcValue = new GivenParameter <double>(Waveform.Value, false);
                }
                else
                {
                    SpiceSharpWarning.Warning(this,
                                              Properties.Resources.IndependentSources_NoDc.FormatString(Name));
                }
            }

            // Connections
            _biasing = context.GetState <IBiasingSimulationState>();
            context.TryGetState(out _method);

            _variables = new OnePort <double>(_biasing, context);
            Branch     = _biasing.CreatePrivateVariable(Name.Combine("branch"), Units.Ampere);
            var pos = _biasing.Map[_variables.Positive];
            var neg = _biasing.Map[_variables.Negative];
            var br  = _biasing.Map[Branch];

            _elements = new ElementSet <double>(_biasing.Solver, new[] {
                new MatrixLocation(pos, br),
                new MatrixLocation(br, pos),
                new MatrixLocation(neg, br),
                new MatrixLocation(br, neg)
            }, new[] { br });
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="BindingContext"/> class.
        /// </summary>
        /// <param name="component">The component creating the behavior.</param>
        /// <param name="simulation">The simulation for which a behavior is created.</param>
        /// <param name="behaviors">The behaviors created by the entity.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="component"/> or <paramref name="simulation"/> is <c>null</c>.</exception>
        public ComponentBindingContext(IComponent component, ISimulation simulation, IBehaviorContainer behaviors)
            : base(component, simulation, behaviors)
        {
            // Get the nodes of the component
            var nodes = component.Nodes;

            string[] myNodes;
            if (nodes != null && nodes.Count > 0)
            {
                myNodes = new string[nodes.Count];
                for (var i = 0; i < nodes.Count; i++)
                {
                    if (nodes[i] == null)
                    {
                        myNodes[i] = Constants.Ground;
                        SpiceSharpWarning.Warning(this, Properties.Resources.Nodes_NullToGround.FormatString(component.Name, i));
                    }
                    else
                    {
                        myNodes[i] = nodes[i];
                    }
                }
            }
            else
            {
                myNodes = Array <string> .Empty();
            }
            Nodes = myNodes;

            // Get the model of the component
            if (component.Model != null)
            {
                ModelBehaviors = simulation.EntityBehaviors[component.Model];
            }
            else
            {
                ModelBehaviors = null;
            }
        }
示例#10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Biasing"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="context"/> is <c>null</c>.</exception>
        public Biasing(IComponentBindingContext context) : base(context)
        {
            context.ThrowIfNull(nameof(context));

            Parameters = context.GetParameterSet <Parameters>();
            _biasing   = context.GetState <IBiasingSimulationState>();
            _iteration = context.GetState <IIterationSimulationState>();
            _variables = new OnePort <double>(_biasing, context);
            context.TryGetState <IIntegrationMethod>(out _method);
            Waveform = Parameters.Waveform?.Create(context);

            // Give some warnings if no value is given
            if (!Parameters.DcValue.Given)
            {
                // no DC value - either have a transient value or none
                SpiceSharpWarning.Warning(this,
                                          Waveform != null
                        ? Properties.Resources.IndependentSources_NoDcUseWaveform.FormatString(Name)
                        : Properties.Resources.IndependentSources_NoDc.FormatString(Name));
            }

            _elements = new ElementSet <double>(_biasing.Solver, null, _variables.GetRhsIndices(_biasing.Map));
        }
示例#11
0
        /// <inheritdoc/>
        protected override void CreateBehaviors(IEntityCollection entities)
        {
            base.CreateBehaviors(entities);
            _transientBehaviors  = EntityBehaviors.GetBehaviorList <ITimeBehavior>();
            _acceptBehaviors     = EntityBehaviors.GetBehaviorList <IAcceptBehavior>();
            _truncatingBehaviors = EntityBehaviors.GetBehaviorList <ITruncatingBehavior>();
            _method.Initialize();

            // Set up initial conditions
            var state = GetState <IBiasingSimulationState>();

            _initialConditions.Clear();
            foreach (var ic in TimeParameters.InitialConditions)
            {
                if (state.ContainsKey(ic.Key))
                {
                    _initialConditions.Add(new ConvergenceAid(state.GetSharedVariable(ic.Key), GetState <IBiasingSimulationState>(), ic.Value));
                }
                else
                {
                    SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_ConvergenceAidVariableNotFound.FormatString(ic.Key));
                }
            }
        }
        /// <summary>
        /// Remap a variable node to an <see cref="IVariable{T}"/>.
        /// </summary>
        /// <typeparam name="T">the variable type.</typeparam>
        /// <param name="factory">The variable factory.</param>
        /// <param name="node">The node.</param>
        /// <param name="ownBranch">The branch.</param>
        /// <returns>The variable.</returns>
        public IVariable <T> MapNode <T>(IVariableFactory <IVariable <T> > factory, VariableNode node, IVariable <T> ownBranch = null)
        {
            switch (node.NodeType)
            {
            case NodeTypes.Voltage:
                return(factory.GetSharedVariable(node.Name));

            case NodeTypes.Current:
                IBehaviorContainer container;
                IBiasingBehavior   tmpb;
                IFrequencyBehavior tmpf;

                // Get the relevant behaviors
                if (Simulation.EntityBehaviors.Comparer.Equals(node.Name, Behaviors.Name))
                {
                    container = Behaviors;
                }
                else
                {
                    container = Simulation.EntityBehaviors[node.Name];
                }

                if (container == Behaviors)
                {
                    if (ownBranch == null)
                    {
                        throw new SpiceSharpException($"The behavior for {Entity.Name} does not define a branch current.");
                    }
                    return(ownBranch);
                }
                else if (container.TryGetValue <IBranchedBehavior <T> >(out var branched))
                {
                    // Best-case scenario! Our behaviors define a branched behavior!
                    return(branched.Branch);
                }
                else if (typeof(T) == typeof(double) && container.TryGetValue(out tmpb) && tmpb is CurrentSources.Biasing biasing)
                {
                    // If whatever is being is asked is the current from a current source, then we also don't have a problem
                    var result = new FuncVariable <double>($"I({biasing.Name})", () => biasing.Current, Units.Ampere);
                    return(result as IVariable <T>);
                }
                else if (typeof(T) == typeof(Complex) && container.TryGetValue(out tmpf) && tmpf is CurrentSources.Frequency frequency)
                {
                    // Current source = no problem
                    var result = new FuncVariable <Complex>($"I({frequency.Name})", () => frequency.ComplexCurrent, Units.Ampere);
                    return(result as IVariable <T>);
                }
                else
                {
                    var result = container.CreatePropertyGetter <T>("i");
                    if (result == null)
                    {
                        goto default;
                    }
                    SpiceSharpWarning.Warning(this, SpiceSharpBehavioral.Properties.Resources.LooseLinkCurrent.FormatString(container.Name));
                    return(new FuncVariable <T>($"@{container.Name}[i]", result, Units.Ampere));
                }

            default:
                throw new SpiceSharpException($"Could not determine the variable {node.Name}");
            }
        }
示例#13
0
        /// <summary>
        /// Iterates towards a solution.
        /// </summary>
        /// <param name="maxIterations">The maximum allowed iterations.</param>
        /// <returns>
        ///   <c>true</c> if the iterations converged to a solution; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="SpiceSharpException">Thrown if any behavior cannot load the matrix and/or right hand side vector, or if the solution
        /// is not a number (NaN).</exception>
        /// <exception cref="SingularException">Thrown if the equation matrix is singular.</exception>
        protected virtual bool Iterate(int maxIterations)
        {
            var solver = _state.Solver;
            var pass   = false;
            var iterno = 0;

            try
            {
                while (true)
                {
                    // Load the Y-matrix and right hand side vector
                    Iteration.IsConvergent = true;
                    Load();
                    iterno++;

                    // Preorder matrix
                    if (!_isPreordered)
                    {
                        solver.Precondition((matrix, vector)
                                            => ModifiedNodalAnalysisHelper <double> .PreorderModifiedNodalAnalysis(matrix, solver.Size - solver.Degeneracy));
                        _isPreordered = true;
                    }
                    if (Iteration.Mode == IterationModes.Junction)
                    {
                        _shouldReorder = true;
                    }

                    if (_shouldReorder)
                    {
                        // Reorder and factor the solver
                        Statistics.ReorderTime.Start();
                        try
                        {
                            var eliminated = solver.OrderAndFactor();
                            if (eliminated < solver.Size)
                            {
                                // We should avoid throwing an exception here, because this may just be a starting
                                // error...
                                SpiceSharpWarning.Warning(this, Properties.Resources.Algebra_SingularMatrixIndexed.FormatString(eliminated + 1));
                                return(false);
                            }
                            _shouldReorder = false;
                        }
                        finally
                        {
                            Statistics.ReorderTime.Stop();
                        }
                    }
                    else
                    {
                        // Just factor the solver (without losing time reordering)
                        Statistics.FactoringTime.Start();
                        try
                        {
                            if (!solver.Factor())
                            {
                                _shouldReorder = true;
                                continue;
                            }
                        }
                        finally
                        {
                            Statistics.FactoringTime.Stop();
                        }
                    }

                    // The current solution becomes the old solution
                    _state.StoreSolution();

                    // Solve the equation
                    Statistics.SolveTime.Start();
                    try
                    {
                        solver.Solve(_state.Solution);
                    }
                    finally
                    {
                        Statistics.SolveTime.Stop();
                    }

                    // Reset ground nodes
                    solver.GetElement(0).Value = 0.0;
                    _state.Solution[0]         = 0.0;
                    _state.OldSolution[0]      = 0.0;

                    // Update
                    foreach (var behavior in _updateBehaviors)
                    {
                        behavior.Update();
                    }

                    // Exceeded maximum number of iterations
                    if (iterno > maxIterations)
                    {
                        return(false);
                    }

                    if (Iteration.IsConvergent && iterno != 1)
                    {
                        Iteration.IsConvergent = IsConvergent();
                    }
                    else
                    {
                        Iteration.IsConvergent = false;
                    }

                    switch (Iteration.Mode)
                    {
                    case IterationModes.Float:
                        if (_nodesets.Count > 0)
                        {
                            if (pass)
                            {
                                Iteration.IsConvergent = false;
                            }
                            pass = false;
                        }
                        if (Iteration.IsConvergent)
                        {
                            return(true);
                        }
                        break;

                    case IterationModes.Junction:
                        Iteration.Mode = IterationModes.Fix;
                        _shouldReorder = true;
                        break;

                    case IterationModes.Fix:
                        if (Iteration.IsConvergent)
                        {
                            Iteration.Mode = IterationModes.Float;
                        }
                        pass = true;
                        break;

                    case IterationModes.None:
                        Iteration.Mode = IterationModes.Float;
                        break;

                    default:
                        throw new SpiceSharpException(Properties.Resources.Simulations_InvalidInitializationMode);
                    }
                }
            }
            finally
            {
                Statistics.Iterations += iterno;
            }
        }
示例#14
0
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member

        /// <summary>
        /// Updates the specified properties.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="p">The parameters of the transistor.</param>
        /// <param name="mp">The model parameters.</param>
        /// <param name="mprp">The model properties.</param>
        public void Update(string name, Parameters p, ModelParameters mp, ModelProperties mprp)
        {
            if (!mp.Transconductance.Given)
            {
                mp.Transconductance = new GivenParameter <double>(mp.SurfaceMobility * mprp.OxideCapFactor * 1e-4, false);
            }
            TempVt = p.Temperature * Constants.KOverQ;
            var ratio = p.Temperature / mp.NominalTemperature;
            var fact2 = p.Temperature / Constants.ReferenceTemperature;
            var kt    = p.Temperature * Constants.Boltzmann;
            var egfet = 1.16 - (7.02e-4 * p.Temperature * p.Temperature) /
                        (p.Temperature + 1108);
            var arg    = -egfet / (kt + kt) + 1.1150877 / (Constants.Boltzmann * (Constants.ReferenceTemperature + Constants.ReferenceTemperature));
            var pbfact = -2 * TempVt * (1.5 * Math.Log(fact2) + Constants.Charge * arg);

            OxideCap = mprp.OxideCapFactor * EffectiveLength * p.ParallelMultiplier * p.Width;

            if (p.Length - 2 * mp.LateralDiffusion <= 0)
            {
                SpiceSharpWarning.Warning(this, "{0}: effective channel length less than zero".FormatString(name));
            }
            var ratio4 = ratio * Math.Sqrt(ratio);

            TempTransconductance = mp.Transconductance / ratio4;
            TempSurfaceMobility  = mp.SurfaceMobility / ratio4;
            var phio = (mp.Phi - mprp.PbFactor1) / mprp.Factor1;

            TempPhi = fact2 * phio + pbfact;
            TempVbi = mp.Vt0 - mp.MosfetType * (mp.Gamma * Math.Sqrt(mp.Phi)) + .5 * (mprp.EgFet1 - egfet) + mp.MosfetType * .5 * (TempPhi - mp.Phi);
            TempVt0 = TempVbi + mp.MosfetType * mp.Gamma * Math.Sqrt(TempPhi);
            var TempSaturationCurrent        = mp.JunctionSatCur * Math.Exp(-egfet / TempVt + mprp.EgFet1 / mprp.Vtnom);
            var TempSaturationCurrentDensity = mp.JunctionSatCurDensity * Math.Exp(-egfet / TempVt + mprp.EgFet1 / mprp.Vtnom);
            var pbo = (mp.BulkJunctionPotential - mprp.PbFactor1) / mprp.Factor1;

            TempBulkPotential = fact2 * pbo + pbfact;

            if ((TempSaturationCurrentDensity == 0) ||
                (p.DrainArea == 0) ||
                (p.SourceArea == 0))
            {
                SourceVCritical = DrainVCritical =
                    TempVt * Math.Log(TempVt / (Constants.Root2 * p.ParallelMultiplier * TempSaturationCurrent));
            }
            else
            {
                DrainVCritical =
                    TempVt * Math.Log(TempVt / (Constants.Root2 *
                                                p.ParallelMultiplier *
                                                TempSaturationCurrentDensity * p.DrainArea));
                SourceVCritical =
                    TempVt * Math.Log(TempVt / (Constants.Root2 *
                                                p.ParallelMultiplier *
                                                TempSaturationCurrentDensity * p.SourceArea));
            }

            if (mp.DrainResistance.Given)
            {
                if (mp.DrainResistance != 0)
                {
                    DrainConductance = p.ParallelMultiplier / mp.DrainResistance;
                }
                else
                {
                    DrainConductance = 0;
                }
            }
            else if (mp.SheetResistance.Given)
            {
                if (mp.SheetResistance != 0)
                {
                    DrainConductance = p.ParallelMultiplier / (mp.SheetResistance * p.DrainSquares);
                }
                else
                {
                    DrainConductance = 0;
                }
            }
            else
            {
                DrainConductance = 0;
            }

            if (mp.SourceResistance.Given)
            {
                if (mp.SourceResistance != 0)
                {
                    SourceConductance = p.ParallelMultiplier / mp.SourceResistance;
                }
                else
                {
                    SourceConductance = 0;
                }
            }
            else if (mp.SheetResistance.Given)
            {
                if ((mp.SheetResistance != 0) && (p.SourceSquares != 0))
                {
                    SourceConductance = p.ParallelMultiplier / (mp.SheetResistance * p.SourceSquares);
                }
                else
                {
                    SourceConductance = 0;
                }
            }
            else
            {
                SourceConductance = 0;
            }

            EffectiveLength = p.Length - (2 * mp.LateralDiffusion);

            var gmaold  = (mp.BulkJunctionPotential - pbo) / pbo;
            var capfact = 1 / (1 + (mp.BulkJunctionBotGradingCoefficient *
                                    ((4e-4 * (mp.NominalTemperature - Constants.ReferenceTemperature)) - gmaold)));

            TempCbd = mp.CapBd * capfact;
            TempCbs = mp.CapBs * capfact;
            TempCj  = mp.BulkCapFactor * capfact;
            capfact = 1 / (1 + (mp.BulkJunctionSideGradingCoefficient *
                                ((4e-4 * (mp.NominalTemperature - Constants.ReferenceTemperature)) - gmaold)));
            TempCjsw          = mp.SidewallCapFactor * capfact;
            TempBulkPotential = (fact2 * pbo) + pbfact;
            var gmanew = (TempBulkPotential - pbo) / pbo;

            capfact = 1 + (mp.BulkJunctionBotGradingCoefficient *
                           ((4e-4 * (p.Temperature - Constants.ReferenceTemperature)) - gmanew));
            TempCbd *= capfact;
            TempCbs *= capfact;
            TempCj  *= capfact;
            capfact  = 1 + (mp.BulkJunctionSideGradingCoefficient *
                            ((4e-4 * (p.Temperature - Constants.ReferenceTemperature)) - gmanew));
            TempCjsw  *= capfact;
            TempDepCap = mp.ForwardCapDepletionCoefficient * TempBulkPotential;

            double czbd, czbdsw;

            if (mp.CapBd.Given)
            {
                czbd = TempCbd * p.ParallelMultiplier;
            }
            else
            {
                if (mp.BulkCapFactor.Given)
                {
                    czbd = TempCj * p.ParallelMultiplier * p.DrainArea;
                }
                else
                {
                    czbd = 0;
                }
            }
            if (mp.SidewallCapFactor.Given)
            {
                czbdsw = TempCjsw * p.DrainPerimeter * p.ParallelMultiplier;
            }
            else
            {
                czbdsw = 0;
            }
            arg = 1 - mp.ForwardCapDepletionCoefficient;
            var sarg   = Math.Exp((-mp.BulkJunctionBotGradingCoefficient) * Math.Log(arg));
            var sargsw = Math.Exp((-mp.BulkJunctionSideGradingCoefficient) * Math.Log(arg));

            Cbd         = czbd;
            CbdSidewall = czbdsw;
            F2d         = (czbd * (1 - (mp.ForwardCapDepletionCoefficient *
                                        (1 + mp.BulkJunctionBotGradingCoefficient))) * sarg / arg)
                          + (czbdsw * (1 - (mp.ForwardCapDepletionCoefficient *
                                            (1 + mp.BulkJunctionSideGradingCoefficient))) *
                             sargsw / arg);
            F3d = (czbd * mp.BulkJunctionBotGradingCoefficient * sarg / arg /
                   TempBulkPotential)
                  + (czbdsw * mp.BulkJunctionSideGradingCoefficient * sargsw / arg /
                     TempBulkPotential);
            F4d = (czbd * TempBulkPotential * (1 - (arg * sarg)) /
                   (1 - mp.BulkJunctionBotGradingCoefficient))
                  + (czbdsw * TempBulkPotential * (1 - (arg * sargsw)) /
                     (1 - mp.BulkJunctionSideGradingCoefficient))
                  - (F3d / 2 *
                     (TempDepCap * TempDepCap))
                  - (TempDepCap * F2d);

            double czbs, czbssw;

            if (mp.CapBs.Given)
            {
                czbs = TempCbs * p.ParallelMultiplier;
            }
            else
            {
                if (mp.BulkCapFactor.Given)
                {
                    czbs = TempCj * p.SourceArea * p.ParallelMultiplier;
                }
                else
                {
                    czbs = 0;
                }
            }
            if (mp.SidewallCapFactor.Given)
            {
                czbssw = TempCjsw * p.SourcePerimeter * p.ParallelMultiplier;
            }
            else
            {
                czbssw = 0;
            }
            arg         = 1 - mp.ForwardCapDepletionCoefficient;
            sarg        = Math.Exp((-mp.BulkJunctionBotGradingCoefficient) * Math.Log(arg));
            sargsw      = Math.Exp((-mp.BulkJunctionSideGradingCoefficient) * Math.Log(arg));
            Cbs         = czbs;
            CbsSidewall = czbssw;
            F2s         = (czbs * (1 - (mp.ForwardCapDepletionCoefficient *
                                        (1 + mp.BulkJunctionBotGradingCoefficient))) * sarg / arg)
                          + (czbssw * (1 - (mp.ForwardCapDepletionCoefficient *
                                            (1 + mp.BulkJunctionSideGradingCoefficient))) *
                             sargsw / arg);
            F3s = (czbs * mp.BulkJunctionBotGradingCoefficient * sarg / arg /
                   TempBulkPotential)
                  + (czbssw * mp.BulkJunctionSideGradingCoefficient * sargsw / arg /
                     TempBulkPotential);
            F4s = (czbs * TempBulkPotential * (1 - (arg * sarg)) /
                   (1 - mp.BulkJunctionBotGradingCoefficient))
                  + (czbssw * TempBulkPotential * (1 - (arg * sargsw)) /
                     (1 - mp.BulkJunctionSideGradingCoefficient))
                  - (F3s / 2 *
                     (TempDepCap * TempDepCap))
                  - (TempDepCap * F2s);
        }
示例#15
0
        /// <inheritdoc/>
        void ITemperatureBehavior.Temperature()
        {
            var xcbv = 0.0;

            // loop through all the instances
            if (!Parameters.Temperature.Given)
            {
                Parameters.Temperature = new GivenParameter <double>(_temperature.Temperature, false);
            }
            Vt  = Constants.KOverQ * Parameters.Temperature;
            Vte = ModelParameters.EmissionCoefficient * Vt;

            // this part gets really ugly - I won't even try to explain these equations
            var fact2 = Parameters.Temperature / Constants.ReferenceTemperature;
            var egfet = 1.16 - 7.02e-4 * Parameters.Temperature * Parameters.Temperature / (Parameters.Temperature + 1108);
            var arg   = -egfet / (2 * Constants.Boltzmann * Parameters.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 * (Parameters.Temperature - Constants.ReferenceTemperature) - gmanew);

            TempSaturationCurrent = ModelParameters.SaturationCurrent * Math.Exp((Parameters.Temperature / ModelParameters.NominalTemperature - 1) * ModelParameters.ActivationEnergy /
                                                                                 (ModelParameters.EmissionCoefficient * Vt) + ModelParameters.SaturationCurrentExp / ModelParameters.EmissionCoefficient * Math.Log(Parameters.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;
                    SpiceSharpWarning.Warning(this,
                                              Properties.Resources.Diodes_BreakdownCurrentIncreased.FormatString(Name, cbv));
                    xbv = ModelParameters.BreakdownVoltage;
                }
                else
                {
                    var tol = BiasingParameters.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)
                    {
                        SpiceSharpWarning.Warning(this,
                                                  Properties.Resources.Diodes_ImpossibleFwdRevMatch.FormatString(Name, xbv, xcbv));
                    }
                }
                TempBreakdownVoltage = xbv;
            }
        }