Exemplo n.º 1
0
        /// <summary>
        /// Execute behaviour
        /// </summary>
        void ITimeBehavior.Load()
        {
            // Initialize
            _flux.ThrowIfNotBound(this).Current = BaseParameters.Inductance * State.Solution[BranchEq];

            // Allow alterations of the flux
            if (UpdateFlux != null)
            {
                var args = new UpdateFluxEventArgs(BaseParameters.Inductance, State.Solution[BranchEq], _flux, State);
                UpdateFlux.Invoke(this, args);
            }

            // Finally load the Y-matrix
            _flux.Integrate();
            BranchPtr.Value       += _flux.RhsCurrent();
            BranchBranchPtr.Value -= _flux.Jacobian(BaseParameters.Inductance);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Execute behaviour
        /// </summary>
        /// <param name="simulation">Time-based simulation</param>
        public override void Transient(TimeSimulation simulation)
        {
            if (simulation == null)
            {
                throw new ArgumentNullException(nameof(simulation));
            }

            var state = simulation.RealState;

            // Initialize
            _flux.Current = _bp.Inductance * state.Solution[_branchEq];

            // Allow alterations of the flux
            if (UpdateFlux != null)
            {
                UpdateFluxEventArgs args = new UpdateFluxEventArgs(_bp.Inductance, state.Solution[_branchEq], _flux, state);
                UpdateFlux.Invoke(this, args);
            }

            // Finally load the Y-matrix
            _flux.Integrate();
            BranchPtr.Value       += _flux.RhsCurrent();
            BranchBranchPtr.Value -= _flux.Jacobian(_bp.Inductance);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Transient behavior
        /// </summary>
        /// <param name="simulation">Time-based simulation</param>
        public override void Transient(TimeSimulation simulation)
        {
            if (simulation == null)
            {
                throw new ArgumentNullException(nameof(simulation));
            }

            double sargsw;

            var vbs   = _load.VoltageBs;
            var vbd   = _load.VoltageBd;
            var vgs   = _load.VoltageGs;
            var vds   = _load.VoltageDs;
            var vgd   = _load.VoltageGs - _load.VoltageDs;
            var vgb   = _load.VoltageGs - _load.VoltageBs;
            var von   = _mbp.MosfetType * _load.Von;
            var vdsat = _mbp.MosfetType * _load.SaturationVoltageDs;

            _vds.Current = vds;
            _vbs.Current = vbs;
            _vgs.Current = vgs;

            var gbd = 0.0;
            var cbd = 0.0;
            var gbs = 0.0;
            var cbs = 0.0;

            var effectiveLength      = _bp.Length - 2 * _mbp.LateralDiffusion;
            var gateSourceOverlapCap = _mbp.GateSourceOverlapCapFactor * _bp.Width;
            var gateDrainOverlapCap  = _mbp.GateDrainOverlapCapFactor * _bp.Width;
            var gateBulkOverlapCap   = _mbp.GateBulkOverlapCapFactor * effectiveLength;
            var oxideCap             = _mbp.OxideCapFactor * effectiveLength * _bp.Width;

            /*
             * now we do the hard part of the bulk - drain and bulk - source
             * diode - we evaluate the non - linear capacitance and
             * charge
             *
             * the basic equations are not hard, but the implementation
             * is somewhat long in an attempt to avoid log / exponential
             * evaluations
             */
            /*
             * charge storage elements
             *
             * .. bulk - drain and bulk - source depletion capacitances
             */

            if (vbs < _temp.TempDepletionCap)
            {
                double arg = 1 - vbs / _temp.TempBulkPotential, sarg;

                /*
                 * the following block looks somewhat long and messy,
                 * but since most users use the default grading
                 * coefficients of .5, and sqrt is MUCH faster than an
                 * Math.Exp(Math.Log()) we use this special case code to buy time.
                 * (as much as 10% of total job time!)
                 */
                if (_mbp.BulkJunctionBotGradingCoefficient.Value.Equals(_mbp.BulkJunctionSideGradingCoefficient))
                {
                    if (_mbp.BulkJunctionBotGradingCoefficient.Value.Equals(0.5))
                    {
                        sarg = sargsw = 1 / Math.Sqrt(arg);
                    }
                    else
                    {
                        sarg = sargsw = Math.Exp(-_mbp.BulkJunctionBotGradingCoefficient * Math.Log(arg));
                    }
                }
                else
                {
                    if (_mbp.BulkJunctionBotGradingCoefficient.Value.Equals(0.5))
                    {
                        sarg = 1 / Math.Sqrt(arg);
                    }
                    else
                    {
                        /* NOSQRT */
                        sarg = Math.Exp(-_mbp.BulkJunctionBotGradingCoefficient * Math.Log(arg));
                    }
                    if (_mbp.BulkJunctionSideGradingCoefficient.Value.Equals(0.5))
                    {
                        sargsw = 1 / Math.Sqrt(arg);
                    }
                    else
                    {
                        /* NOSQRT */
                        sargsw = Math.Exp(-_mbp.BulkJunctionSideGradingCoefficient * Math.Log(arg));
                    }
                }
                /* NOSQRT */
                _qbs.Current = _temp.TempBulkPotential * (_temp.CapBs * (1 - arg * sarg) / (1 - _mbp.BulkJunctionBotGradingCoefficient) +
                                                          _temp.CapBsSidewall * (1 - arg * sargsw) / (1 - _mbp.BulkJunctionSideGradingCoefficient));
                CapBs = _temp.CapBs * sarg + _temp.CapBsSidewall * sargsw;
            }
            else
            {
                _qbs.Current = _temp.F4S + vbs * (_temp.F2S + vbs * (_temp.F3S / 2));
                CapBs        = _temp.F2S + _temp.F3S * vbs;
            }

            if (vbd < _temp.TempDepletionCap)
            {
                double arg = 1 - vbd / _temp.TempBulkPotential, sarg;

                /*
                 * the following block looks somewhat long and messy,
                 * but since most users use the default grading
                 * coefficients of .5, and sqrt is MUCH faster than an
                 * Math.Exp(Math.Log()) we use this special case code to buy time.
                 * (as much as 10% of total job time!)
                 */
                if (_mbp.BulkJunctionBotGradingCoefficient.Value.Equals(0.5) && _mbp.BulkJunctionSideGradingCoefficient.Value.Equals(0.5))
                {
                    sarg = sargsw = 1 / Math.Sqrt(arg);
                }
                else
                {
                    if (_mbp.BulkJunctionBotGradingCoefficient.Value.Equals(0.5))
                    {
                        sarg = 1 / Math.Sqrt(arg);
                    }
                    else
                    {
                        /* NOSQRT */
                        sarg = Math.Exp(-_mbp.BulkJunctionBotGradingCoefficient * Math.Log(arg));
                    }
                    if (_mbp.BulkJunctionSideGradingCoefficient.Value.Equals(0.5))
                    {
                        sargsw = 1 / Math.Sqrt(arg);
                    }
                    else
                    {
                        /* NOSQRT */
                        sargsw = Math.Exp(-_mbp.BulkJunctionSideGradingCoefficient * Math.Log(arg));
                    }
                }
                /* NOSQRT */
                _qbd.Current = _temp.TempBulkPotential * (_temp.CapBd * (1 - arg * sarg) / (1 - _mbp.BulkJunctionBotGradingCoefficient) +
                                                          _temp.CapBdSidewall * (1 - arg * sargsw) / (1 - _mbp.BulkJunctionSideGradingCoefficient));
                CapBd = _temp.CapBd * sarg + _temp.CapBdSidewall * sargsw;
            }
            else
            {
                _qbd.Current = _temp.F4D + vbd * (_temp.F2D + vbd * _temp.F3D / 2);
                CapBd        = _temp.F2D + vbd * _temp.F3D;
            }
            /* CAPZEROBYPASS */

            /* (above only excludes tranop, since we're only at this
             * point if tran or tranop)
             */

            /*
             * calculate equivalent conductances and currents for
             * depletion capacitors
             */

            /* integrate the capacitors and save results */
            _qbd.Integrate();
            gbd += _qbd.Jacobian(CapBd);
            cbd += _qbd.Derivative;
            _qbs.Integrate();
            gbs += _qbs.Jacobian(CapBs);
            cbs += _qbs.Derivative;

            /*
             * calculate meyer's capacitors
             */
            /*
             * new cmeyer - this just evaluates at the current time,
             * expects you to remember values from previous time
             * returns 1 / 2 of non - constant portion of capacitance
             * you must add in the other half from previous time
             * and the constant part
             */
            double icapgs, icapgd, icapgb;

            if (_load.Mode > 0)
            {
                Transistor.MeyerCharges(vgs, vgd, von, vdsat,
                                        out icapgs, out icapgd, out icapgb, _temp.TempPhi, oxideCap);
            }
            else
            {
                Transistor.MeyerCharges(vgd, vgs, von, vdsat,
                                        out icapgd, out icapgs, out icapgb, _temp.TempPhi, oxideCap);
            }
            _capgs.Current = icapgs;
            _capgd.Current = icapgd;
            _capgb.Current = icapgb;

            var vgs1  = _vgs[1];
            var vgd1  = vgs1 - _vds[1];
            var vgb1  = vgs1 - _vbs[1];
            var capgs = _capgs.Current + _capgs[1] + gateSourceOverlapCap;
            var capgd = _capgd.Current + _capgd[1] + gateDrainOverlapCap;
            var capgb = _capgb.Current + _capgb[1] + gateBulkOverlapCap;

            _qgs.Current = (vgs - vgs1) * capgs + _qgs[1];
            _qgd.Current = (vgd - vgd1) * capgd + _qgd[1];
            _qgb.Current = (vgb - vgb1) * capgb + _qgb[1];

            /*
             * calculate equivalent conductances and currents for
             * meyer"s capacitors
             */
            _qgs.Integrate();
            var gcgs  = _qgs.Jacobian(capgs);
            var ceqgs = _qgs.RhsCurrent(gcgs, vgs);

            _qgd.Integrate();
            var gcgd  = _qgd.Jacobian(capgd);
            var ceqgd = _qgd.RhsCurrent(gcgd, vgd);

            _qgb.Integrate();
            var gcgb  = _qgb.Jacobian(capgb);
            var ceqgb = _qgb.RhsCurrent(gcgb, vgb);

            // Load current vector
            var ceqbs = _mbp.MosfetType * (cbs - gbs * vbs);
            var ceqbd = _mbp.MosfetType * (cbd - gbd * vbd);

            GatePtr.Value        -= _mbp.MosfetType * (ceqgs + ceqgb + ceqgd);
            BulkPtr.Value        -= ceqbs + ceqbd - _mbp.MosfetType * ceqgb;
            DrainPrimePtr.Value  += ceqbd + _mbp.MosfetType * ceqgd;
            SourcePrimePtr.Value += ceqbs + _mbp.MosfetType * ceqgs;

            // Load y matrix
            GateGatePtr.Value               += gcgd + gcgs + gcgb;
            BulkBulkPtr.Value               += gbd + gbs + gcgb;
            DrainPrimeDrainPrimePtr.Value   += gbd + gcgd;
            SourcePrimeSourcePrimePtr.Value += gbs + gcgs;
            GateBulkPtr.Value               -= gcgb;
            GateDrainPrimePtr.Value         -= gcgd;
            GateSourcePrimePtr.Value        -= gcgs;
            BulkGatePtr.Value               -= gcgb;
            BulkDrainPrimePtr.Value         -= gbd;
            BulkSourcePrimePtr.Value        -= gbs;
            DrainPrimeGatePtr.Value         += -gcgd;
            DrainPrimeBulkPtr.Value         += -gbd;
            SourcePrimeGatePtr.Value        += -gcgs;
            SourcePrimeBulkPtr.Value        += -gbs;
        }