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)); } }
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 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); }
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)); */ }