Exemple #1
0
        public ChargeDensity GetChargeY(ElectricPotential potential)
        {
            var vT = ThermalVoltage;

            if (DopingType == DopingType.P)
            {
                var cConc = ElectricCharge.Elementary *
                            (FreeHoleConcentration * Math.Exp(-potential / vT)
                             - FreeElectronConcentration * Math.Exp(potential / vT)
                             - DopantConcentration);

                // Apparently this is ok, but I don't know why - RT
                return(ChargeDensity.FromCoulombsPerSquareCentimeter(cConc.CoulombsPerCubicCentimeter));
            }
            else
            {
                var cConc = -ElectricCharge.Elementary *
                            (FreeElectronConcentration * Math.Exp(potential / vT)
                             - FreeHoleConcentration * Math.Exp(-potential / vT)
                             - DopantConcentration);

                // Apparently this is ok, but I don't know why - RT
                return(ChargeDensity.FromCoulombsPerSquareCentimeter(cConc.CoulombsPerCubicCentimeter));
            }
        }
Exemple #2
0
 public override int GetHashCode()
 {
     return(ChargeDensity.GetHashCode()
            ^ ElectricField.GetHashCode()
            ^ Location.GetHashCode()
            ^ Potential.GetHashCode());
 }
Exemple #3
0
        private bool ShouldKeepTryingSurfacePotential(ChargeDensity charge,
                                                      ChargeDensity guessCharge, int iterationNumber)
        {
            var maxDelta = ChargeDensity.FromCoulombsPerSquareCentimeter(Math.Abs(charge.CoulombsPerSquareCentimeter * 1e-6));

            return(((charge - maxDelta > guessCharge) || (guessCharge > charge + maxDelta)) &&
                   iterationNumber < 1000);
        }
        public ChargeDensity(ChargeDensity chargeDensity)
        {
            Name = chargeDensity.Name;
            Type = chargeDensity.Type;
            _density = chargeDensity.Density;
            _electricCharge = chargeDensity.ElectricCharge;

            _bodySurface = new Helper.Area(chargeDensity.BodySurface.Height, chargeDensity.BodySurface.Width);
            IsActive = chargeDensity.IsActive;
        }
        public ChargeDensity(ChargeDensity chargeDensity)
        {
            Name            = chargeDensity.Name;
            Type            = chargeDensity.Type;
            _density        = chargeDensity.Density;
            _electricCharge = chargeDensity.ElectricCharge;

            _bodySurface = new Helper.Area(chargeDensity.BodySurface.Height, chargeDensity.BodySurface.Width);
            IsActive     = chargeDensity.IsActive;
        }
        public SurfaceSettings(ChargeDensity chargeDensity)
        {
            InitializeComponent();
            ChrDensity = new ChargeDensity(chargeDensity);
            cmboxChargeType.SelectedIndex = chargeDensity.Type == Charge.ChargeType.Positive ? 0 : 1;

            doubleUDCharge.Value  = chargeDensity.ElectricCharge;
            doubleUDDensity.Value = chargeDensity.Density;

            intUDHeight.Value = chargeDensity.BodySurface.Height;
            intUDWidth.Value  = chargeDensity.BodySurface.Width;
        }
Exemple #7
0
        public void ShowSettings()
        {
            var  setting = new SurfaceSettings(MyCharge);
            bool?result  = setting.ShowDialog();

            if (result == true)
            {
                MyCharge = new ChargeDensity(setting.ChrDensity);
                MainWindow.Instance.Calculation();
                CheckColor();
            }
        }
        public void TestCalculatesSurfacePotentialCorrectly()
        {
            var shellStructure = new Structure();

            shellStructure.Temperature = new Temperature(300);

            var semiconductor = CreateTestSemiconductor();

            shellStructure.AddLayer(semiconductor);

            var testCharge = ChargeDensity.FromCoulombsPerSquareCentimeter(-.25);

            var potential        = semiconductor.GetSurfacePotential(testCharge);
            var roundedPotential = Math.Round(potential.Volts, 3);

            Assert.AreEqual(.766, roundedPotential);
        }
Exemple #9
0
        public ChargeDensity GetDepletionCharge(ElectricPotential surfacePotential)
        {
            if (DopingType == DopingType.P)
            {
                if (surfacePotential <= ElectricPotential.Zero)
                {
                    return(ChargeDensity.Zero);
                }

                var realSurfacePotential = surfacePotential - ThermalVoltage;
                var value = -SemiconductorConstant *Math.Sqrt(realSurfacePotential.Volts);

                return(ChargeDensity.FromCoulombsPerSquareCentimeter(value));
            }
            else
            {
                // TODO: Implement for N type!
                throw new NotImplementedException();
            }
        }
Exemple #10
0
        public ChargeDensity GetChargeDensity(ElectricPotential surfacePotential)
        {
            var vT = ThermalVoltage;
            ElectricPotential innerTerm;

            if (DopingType == DopingType.P)
            {
                innerTerm = vT * Math.Exp(-surfacePotential / vT)
                            + surfacePotential - vT + Math.Exp(-2 * PhiF / vT)
                            * (vT * Math.Exp(surfacePotential / vT) - surfacePotential - vT);
            }
            else
            {
                innerTerm = vT * Math.Exp(surfacePotential / vT)
                            - surfacePotential - vT + Math.Exp(2 * PhiF / vT)
                            * (vT * Math.Exp(-surfacePotential / vT) - surfacePotential - vT);
            }

            var charge = ChargeDensity.FromCoulombsPerSquareCentimeter(SemiconductorConstant * Math.Sqrt(innerTerm.Volts));

            return(surfacePotential >= ElectricPotential.Zero ? -charge : charge);
        }
 public void RemoveExistingCharge(ChargeDensity charge, UIElement element)
 {
     gridField.Children.Remove(element);
     Calculation();
     FieldOutline.Update();
 }
        // Calculate based on top charge return running charge
        private ChargeDensity EvaluateGivenCharge(ChargeDensity topCharge, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Set the top metal to have a charge at the bottom (location = thickness)
            TopLayer.Prepare();

            // Set the first point to all zeros
            TopLayer.EvalPoints[0] = new EvalPoint();

            // Add charge to the last point
            TopLayer.EvalPoints[1] = new EvalPoint
            {
                Location      = TopLayer.Thickness,
                ChargeDensity = topCharge
            };

            var runningCharge    = topCharge;
            var runningPotential = ElectricPotential.Zero;

            // Now integrate the charges to get the electric field in all the dielectrics
            foreach (var layer in Layers.Skip(1).Take(Layers.Count - 2)) // Only inner layers
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(ChargeDensity.Zero);
                }

                if (layer is Dielectric)
                {
                    var dielectric = (Dielectric)layer;
                    dielectric.Prepare();

                    for (var i = 0; i < dielectric.EvalPoints.Count; i++)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            return(ChargeDensity.Zero);
                        }

                        var point = dielectric.EvalPoints[i];

                        // Integrate the charge (sum really)
                        runningCharge += point.ChargeDensity;

                        // Calculate the Electric Field
                        point.ElectricField = runningCharge / dielectric.Permittivity;

                        // Calculate the potential
                        if (i == 0)
                        {
                            point.Potential = runningPotential;
                        }
                        else
                        {
                            var previousPoint = dielectric.EvalPoints[i - 1];
                            runningPotential -= previousPoint.ElectricField
                                                * (point.Location - previousPoint.Location);

                            point.Potential = runningPotential;
                        }
                    }
                }
                else if (layer is Metal)
                {
                    var metal = (Metal)layer;
                    metal.Prepare();

                    // For the first point put the neg of the charge we have accumulated so far
                    metal.EvalPoints[0].ChargeDensity = -runningCharge;
                    metal.EvalPoints[0].ElectricField = ElectricField.Zero;
                    metal.EvalPoints[0].Potential     = runningPotential;

                    // For the last point put the accumulated charge plus the free charge
                    runningCharge += metal.ExtraCharge; // Integrate the extra charge
                    metal.EvalPoints[1].ChargeDensity = runningCharge;
                    metal.EvalPoints[1].ElectricField = ElectricField.Zero;
                    metal.EvalPoints[1].Potential     = runningPotential;
                }
                else // layer is Semiconductor
                {
                    // do nothing
                }
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(ChargeDensity.Zero);
            }

            // Now add the stuff for the last point - here we assume that it is a metal
            if (IsBottomLayerMetal)
            {
                var metal = (Metal)BottomLayer;
                metal.Prepare();

                // For the first point put the neg of the charge we have accumulated so far
                metal.EvalPoints[0].ChargeDensity = -runningCharge;
                metal.EvalPoints[0].ElectricField = ElectricField.Zero;
                metal.EvalPoints[0].Potential     = runningPotential;

                // For the last point put no charge
                metal.EvalPoints[1].ChargeDensity = ChargeDensity.Zero;
                metal.EvalPoints[1].ElectricField = ElectricField.Zero;
                metal.EvalPoints[1].Potential     = runningPotential;
            }
            else if (IsBottomLayerSemiconductor)
            {
                var semiconductor = (Semiconductor)BottomLayer;

                // Calculate the surface potential and prepare
                semiconductor.ExtraCharge = -runningCharge;
                semiconductor.Prepare();

                // Evaulate the potential drop given the remaining charge
                semiconductor.EvalPoints[0].ChargeDensity = -runningCharge;
                semiconductor.EvalPoints[0].Potential     = runningPotential;

                if (cancellationToken.IsCancellationRequested)
                {
                    return(ChargeDensity.Zero);
                }

                // Last Point
                semiconductor.EvalPoints[1].Potential
                    = runningPotential - semiconductor.SurfacePotential;
            }

            return(runningCharge);
        }
        private void Evaluate(CancellationToken cancellationToken = default(CancellationToken))
        {
            // Don't do anything if the structure isn't valid
            if (!IsValid)
            {
                return;
            }

            int iterationNumber;

            // Since we integrate left to right, we want to specify the voltage on the left
            var voltageBias = -Bias + WorkFunctionDifference;

            // Iterate until we find the desired voltage
            var chargeHigh  = ChargeDensity.FromCoulombsPerSquareCentimeter(1.0);
            var chargeLow   = ChargeDensity.FromCoulombsPerSquareCentimeter(-1.0);
            var chargeGuess = (chargeHigh + chargeLow) / 2;

            // !!!!!!!!!!!!!!!!!!
            EvaluateGivenCharge(chargeGuess, cancellationToken);
            // !!!!!!!!!!!!!!!!!!

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            var potentialCalc    = BottomLayer.EvalPoints[1].Potential;
            var tinyPositiveBias = new ElectricPotential(1e-6);
            var tinyNegativeBias = new ElectricPotential(-1e-6);

            // Iterate
            for (iterationNumber = 0;
                 (potentialCalc > voltageBias + ElectricPotential.Abs(voltageBias * 1e-6)
                  + tinyPositiveBias ||
                  potentialCalc < voltageBias - ElectricPotential.Abs(voltageBias * 1e-6)
                  + tinyNegativeBias) &&
                 iterationNumber < maximumIterations;
                 iterationNumber++)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                if (potentialCalc > voltageBias)
                {
                    chargeLow = chargeGuess;
                }
                else
                {
                    chargeHigh = chargeGuess;
                }

                // Update the guessCharge
                chargeGuess = (chargeHigh + chargeLow) / 2;

                // !!!!!!!!!!!!!!!!!!
                EvaluateGivenCharge(chargeGuess, cancellationToken);
                // !!!!!!!!!!!!!!!!!!

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                potentialCalc = BottomLayer.EvalPoints[1].Potential;

                if (iterationNumber == maximumIterations - 1)
                {
                    if (!(potentialCalc > voltageBias + ElectricPotential.FromMillivolts(1) ||
                          potentialCalc < voltageBias - ElectricPotential.FromMillivolts(1)))
                    {
                        // TODO: Inform that solution only found to accuracy of 1e-3
                    }
                    else
                    {
                        NoSolution = true;
                        return;
                    }
                }
            }

            // If the last material is a semiconductor, fill in the missing points
            if (IsBottomLayerSemiconductor)
            {
                ((Semiconductor)BottomLayer).Evaluate();

                // Now subtract the potential from all the points so the right is ref to 0
                var lastPoint = BottomLayer.EvalPoints.Last();
                var potential = lastPoint.Potential;

                foreach (var layer in Layers)
                {
                    foreach (var ep in layer.EvalPoints)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        ep.Potential = ep.Potential - potential;
                    }
                }

                var trueLast = lastPoint.DeepClone();
                if (trueLast.Location < Length.FromNanometers(50))
                {
                    trueLast.Location = Length.FromNanometers(50);
                }
                BottomLayer.EvalPoints.Add(trueLast);
            }

            NoSolution = false;

            /*
             * Debug.WriteLine(String.Format("Evaluation finished after {0} iterations in {1} ms",
             *  iterationNumber, stopwatch.ElapsedMilliseconds));
             */
        }
Exemple #14
0
 public Surface(ChargeDensity chargeDensity)
 {
     InitializeComponent();
     MyCharge = new ChargeDensity(chargeDensity);
     CheckColor();
 }