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)); } }
public override int GetHashCode() { return(ChargeDensity.GetHashCode() ^ ElectricField.GetHashCode() ^ Location.GetHashCode() ^ Potential.GetHashCode()); }
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 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; }
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); }
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(); } }
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)); */ }
public Surface(ChargeDensity chargeDensity) { InitializeComponent(); MyCharge = new ChargeDensity(chargeDensity); CheckColor(); }