Exemple #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Frequency"/> class.
 /// </summary>
 /// <param name="context">The binding context.</param>
 /// <exception cref="ArgumentNullException">Thrown if <paramref name="context"/> is <c>null</c>.</exception>
 public Frequency(IComponentBindingContext context)
     : base(context)
 {
     ModelParameters = context.ModelBehaviors.GetParameterSet <ModelParameters>();
     Behavior        = context.Behaviors.GetValue <IMosfetBiasingBehavior>();
     _complex        = context.GetState <IComplexSimulationState>();
     Variables       = new MosfetVariables <Complex>(context, _complex);
     _elements       = new ElementSet <Complex>(_complex.Solver, Variables.GetMatrixLocations(_complex.Map));
 }
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member

        /// <summary>
        /// Updates the model properties.
        /// </summary>
        /// <param name="mp">The model parameters.</param>
        public void Update(ModelParameters mp)
        {
            OxideCapFactor = 3.9 * 8.854214871e-12 / mp.OxideThickness;
            Vtnom          = mp.NominalTemperature * Constants.KOverQ;
            Factor1        = mp.NominalTemperature / Constants.ReferenceTemperature;
            Kt1            = Constants.Boltzmann * mp.NominalTemperature;
            EgFet1         = 1.16 - (7.02e-4 * mp.NominalTemperature * mp.NominalTemperature) / (mp.NominalTemperature + 1108);
            var arg1 = -EgFet1 / (Kt1 + Kt1) + 1.1150877 / (Constants.Boltzmann * Constants.ReferenceTemperature * 2);

            PbFactor1 = -2 * Vtnom * (1.5 * Math.Log(Factor1) + Constants.Charge * arg1);
        }
Exemple #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Frequency"/> class.
 /// </summary>
 /// <param name="context">The binding context.</param>
 /// <exception cref="ArgumentNullException">Thrown if <paramref name="context"/> is <c>null</c>.</exception>
 public Frequency(IComponentBindingContext context)
     : base(context)
 {
     ModelParameters = context.ModelBehaviors.GetParameterSet <ModelParameters>();
     Behavior        = context.Behaviors.GetValue <IMosfetBiasingBehavior>();
     _complex        = context.GetState <IComplexSimulationState>();
     Variables       = new MosfetVariables <Complex>(Name, _complex, context.Nodes,
                                                     !ModelParameters.DrainResistance.Equals(0.0) || !ModelParameters.SheetResistance.Equals(0.0) && Behavior.Parameters.DrainSquares > 0,
                                                     !ModelParameters.SourceResistance.Equals(0.0) || !ModelParameters.SheetResistance.Equals(0.0) && Behavior.Parameters.SourceSquares > 0);
     _elements = new ElementSet <Complex>(_complex.Solver, Variables.GetMatrixLocations(_complex.Map));
 }
Exemple #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Time"/> class.
        /// </summary>
        /// <param name="context">The binding context.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="context"/> is <c>null</c>.</exception>
        public Time(IComponentBindingContext context)
            : base(context)
        {
            context.ThrowIfNull(nameof(context));
            _time     = context.GetState <ITimeSimulationState>();
            _behavior = context.Behaviors.GetValue <IMosfetBiasingBehavior>();
            _mp       = context.ModelBehaviors.GetParameterSet <ModelParameters>();
            var method = context.GetState <IIntegrationMethod>();

            _vgs = new StateValue <double>(2); method.RegisterState(_vgs);
            _vds = new StateValue <double>(2); method.RegisterState(_vds);
            _vbs = new StateValue <double>(2); method.RegisterState(_vbs);
            _cgs = new StateValue <double>(2); method.RegisterState(_cgs);
            _cgd = new StateValue <double>(2); method.RegisterState(_cgd);
            _cgb = new StateValue <double>(2); method.RegisterState(_cgb);
            _qgs = method.CreateDerivative();
            _qgd = method.CreateDerivative();
            _qgb = method.CreateDerivative();
            _qbd = method.CreateDerivative();
            _qbs = method.CreateDerivative();
            _behavior.UpdateContributions += UpdateTime;
        }
        /// <summary>
        /// Updates the charges and capacitances..
        /// </summary>
        /// <param name="mode">The mode.</param>
        /// <param name="vgs">The gate-source voltage.</param>
        /// <param name="vds">The drain-source voltage.</param>
        /// <param name="vbs">The bulk-source voltage.</param>
        /// <param name="von">The threshold voltage.</param>
        /// <param name="vdsat">The saturation voltage.</param>
        /// <param name="mp">The model parameters.</param>
        /// <param name="tp">The temperature-dependent properties.</param>
        public void Update(double mode, double vgs, double vds, double vbs, double von, double vdsat,
                           ModelParameters mp,
                           TemperatureProperties tp)
        {
            var    vbd = vbs - vds;
            var    vgd = vgs - vds;
            double arg, sarg, sargsw;

            /*
             * 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
             */

            // Can't bypass the diode capacitance calculations
            if (!tp.Cbs.Equals(0.0) || !tp.CbsSidewall.Equals(0.0))
            {
                if (vbs < tp.TempDepCap)
                {
                    arg = 1 - vbs / tp.TempBulkPotential;

                    /*
                     * 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 (mp.BulkJunctionBotGradingCoefficient.Equals(mp.BulkJunctionSideGradingCoefficient))
                    {
                        if (mp.BulkJunctionBotGradingCoefficient.Equals(0.5))
                        {
                            sarg = sargsw = 1 / Math.Sqrt(arg);
                        }
                        else
                        {
                            sarg = sargsw =
                                Math.Exp(-mp.BulkJunctionBotGradingCoefficient *
                                         Math.Log(arg));
                        }
                    }
                    else
                    {
                        if (mp.BulkJunctionBotGradingCoefficient.Equals(0.5))
                        {
                            sarg = 1 / Math.Sqrt(arg);
                        }
                        else
                        {
                            sarg = Math.Exp(-mp.BulkJunctionBotGradingCoefficient *
                                            Math.Log(arg));
                        }
                        if (mp.BulkJunctionSideGradingCoefficient.Equals(0.5))
                        {
                            sargsw = 1 / Math.Sqrt(arg);
                        }
                        else
                        {
                            sargsw = Math.Exp(-mp.BulkJunctionSideGradingCoefficient *
                                              Math.Log(arg));
                        }
                    }
                    Qbs = tp.TempBulkPotential * (tp.Cbs *
                                                  (1 - arg * sarg) / (1 - mp.BulkJunctionBotGradingCoefficient)
                                                  + tp.CbsSidewall *
                                                  (1 - arg * sargsw) /
                                                  (1 - mp.BulkJunctionSideGradingCoefficient));
                    Cbs = tp.Cbs * sarg + tp.CbsSidewall * sargsw;
                }
                else
                {
                    Qbs = tp.F4s + vbs * (tp.F2s + vbs * (tp.F3s / 2));
                    Cbs = tp.F2s + tp.F3s * vbs;
                }
            }
            else
            {
                Qbs = 0;
                Cbs = 0;
            }

            // can't bypass the diode capacitance calculations
            if (!tp.Cbd.Equals(0.0) || !tp.CbdSidewall.Equals(0.0))
            {
                if (vbd < tp.TempDepCap)
                {
                    arg = 1 - vbd / tp.TempBulkPotential;

                    /*
                     * 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 (mp.BulkJunctionBotGradingCoefficient.Equals(0.5) &&
                        mp.BulkJunctionSideGradingCoefficient.Equals(0.5))
                    {
                        sarg = sargsw = 1 / Math.Sqrt(arg);
                    }
                    else
                    {
                        if (mp.BulkJunctionBotGradingCoefficient == .5)
                        {
                            sarg = 1 / Math.Sqrt(arg);
                        }
                        else
                        {
                            sarg = Math.Exp(-mp.BulkJunctionBotGradingCoefficient *
                                            Math.Log(arg));
                        }
                        if (mp.BulkJunctionSideGradingCoefficient == .5)
                        {
                            sargsw = 1 / Math.Sqrt(arg);
                        }
                        else
                        {
                            sargsw = Math.Exp(-mp.BulkJunctionSideGradingCoefficient *
                                              Math.Log(arg));
                        }
                    }
                    Qbd = tp.TempBulkPotential * (tp.Cbd *
                                                  (1 - arg * sarg)
                                                  / (1 - mp.BulkJunctionBotGradingCoefficient)
                                                  + tp.CbdSidewall *
                                                  (1 - arg * sargsw)
                                                  / (1 - mp.BulkJunctionSideGradingCoefficient));
                    Cbd = tp.Cbd * sarg + tp.CbdSidewall * sargsw;
                }
                else
                {
                    Qbd = tp.F4d + vbd * (tp.F2d + vbd * tp.F3d / 2);
                    Cbd = tp.F2d + vbd * tp.F3d;
                }
            }
            else
            {
                Qbd = 0;
                Cbd = 0;
            }

            // Calculate Meyer capacitances
            double cgs, cgd, cgb;

            if (mode > 0)
            {
                Transistor.MeyerCharges(vgs, vgd, von, vdsat, out cgs, out cgd, out cgb, tp.TempPhi, tp.OxideCap);
            }
            else
            {
                Transistor.MeyerCharges(vgd, vgs, von, vdsat, out cgd, out cgs, out cgb, tp.TempPhi, tp.OxideCap);
            }
            Cgs = cgs;
            Cgd = cgd;
            Cgb = cgb;
        }
Exemple #6
0
        /// <summary>
        /// Calculates the charges and capacitances for the specified voltages.
        /// </summary>
        /// <param name="behavior">The biasing behavior.</param>
        /// <param name="mp">The model parameters.</param>
        public void Calculate(IMosfetBiasingBehavior behavior, ModelParameters mp)
        {
            var tp  = behavior.Properties;
            var vgs = behavior.Vgs;
            var vds = behavior.Vds;
            var vbs = behavior.Vbs;

            /*
             * 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.
             */

            // Bulk-source depletion capacitances
            {
                /* can't bypass the diode capacitance calculations */
                if (tp.Cbs != 0 || tp.CbsSidewall != 0)
                {
                    if (vbs < tp.TempDepCap)
                    {
                        double arg = 1 - vbs / tp.TempBulkPotential;
                        double sarg, sargsw;

                        /*
                         * 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 (mp.BulkJunctionBotGradingCoefficient == mp.BulkJunctionSideGradingCoefficient)
                        {
                            if (mp.BulkJunctionBotGradingCoefficient == .5)
                            {
                                sarg = sargsw = 1 / Math.Sqrt(arg);
                            }
                            else
                            {
                                sarg = sargsw = Math.Exp(-mp.BulkJunctionBotGradingCoefficient * Math.Log(arg));
                            }
                        }
                        else
                        {
                            if (mp.BulkJunctionBotGradingCoefficient == .5)
                            {
                                sarg = 1 / Math.Sqrt(arg);
                            }
                            else
                            {
                                sarg = Math.Exp(-mp.BulkJunctionBotGradingCoefficient * Math.Log(arg));
                            }
                            if (mp.BulkJunctionSideGradingCoefficient == .5)
                            {
                                sargsw = 1 / Math.Sqrt(arg);
                            }
                            else
                            {
                                sargsw = Math.Exp(-mp.BulkJunctionSideGradingCoefficient * Math.Log(arg));
                            }
                        }
                        Qbs = tp.TempBulkPotential * (tp.Cbs *
                                                      (1 - arg * sarg) / (1 - mp.BulkJunctionBotGradingCoefficient)
                                                      + tp.CbsSidewall *
                                                      (1 - arg * sargsw) /
                                                      (1 - mp.BulkJunctionSideGradingCoefficient));
                        Cbs = tp.Cbs * sarg + tp.CbsSidewall * sargsw;
                    }
                    else
                    {
                        Qbs = tp.F4s + vbs * (tp.F2s + vbs * (tp.F3s / 2));
                        Cbs = tp.F2s + tp.F3s * vbs;
                    }
                }
                else
                {
                    Qbs = 0;
                    Cbs = 0;
                }
            }

            // Bulk-drain depletion capacitances
            {
                var vbd = vbs - vds;
                if (tp.Cbd != 0 || tp.CbdSidewall != 0)
                {
                    if (vbd < tp.TempDepCap)
                    {
                        double arg = 1 - vbd / tp.TempBulkPotential;
                        double sarg, sargsw;

                        /*
                         * 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 (mp.BulkJunctionBotGradingCoefficient == .5 && mp.BulkJunctionSideGradingCoefficient == .5)
                        {
                            sarg = sargsw = 1 / Math.Sqrt(arg);
                        }
                        else
                        {
                            if (mp.BulkJunctionBotGradingCoefficient == .5)
                            {
                                sarg = 1 / Math.Sqrt(arg);
                            }
                            else
                            {
                                sarg = Math.Exp(-mp.BulkJunctionBotGradingCoefficient * Math.Log(arg));
                            }
                            if (mp.BulkJunctionSideGradingCoefficient == .5)
                            {
                                sargsw = 1 / Math.Sqrt(arg);
                            }
                            else
                            {
                                sargsw = Math.Exp(-mp.BulkJunctionSideGradingCoefficient * Math.Log(arg));
                            }
                        }
                        Qbd = tp.TempBulkPotential * (tp.Cbd *
                                                      (1 - arg * sarg)
                                                      / (1 - mp.BulkJunctionBotGradingCoefficient)
                                                      + tp.CbdSidewall *
                                                      (1 - arg * sargsw)
                                                      / (1 - mp.BulkJunctionSideGradingCoefficient));
                        Cbd = tp.Cbd * sarg +
                              tp.CbdSidewall * sargsw;
                    }
                    else
                    {
                        Qbd = tp.F4d + vbd * (tp.F2d + vbd * tp.F3d / 2);
                        Cbd = tp.F2d + vbd * tp.F3d;
                    }
                }
                else
                {
                    Qbd = 0;
                    Cbd = 0;
                }
            }

            // Meyer capacitance calculation
            {
                /*
                 * 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 cgs, cgd, cgb;
                if (behavior.Mode > 0)
                {
                    Transistor.MeyerCharges(vgs, vgs - vds, mp.MosfetType * behavior.Von, mp.MosfetType * behavior.Vdsat, out cgs, out cgd, out cgb, tp.TempPhi, tp.OxideCap);
                }
                else
                {
                    Transistor.MeyerCharges(vgs - vds, vgs, mp.MosfetType * behavior.Von, mp.MosfetType * behavior.Vdsat, out cgd, out cgs, out cgb, tp.TempPhi, tp.OxideCap);
                }
                Cgs = cgs;
                Cgd = cgd;
                Cgb = cgb;
            }
        }
Exemple #7
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);
        }