JuliaPhysics/SolidStateDetectors.jl

Depletion and general pn junctions

leenderthayen opened this issue · 8 comments

Hello everyone,

I am wondering how the code actually deals with the impurity density profile and depletion. My current assumption is that the code assumes a standard pn junction to have a vanishingly small heavily doped side and assumes the 1D approximation where the depletion depth is independent of the heavily doped side. If this is the case, I understand that this is fine in Ge detectors because of the substantial crystal size. We would like to explicitly simulate both a p+ window (on n type bulk) and n+ implantation and pstop/pspray on the Ohmic side with varying thickness. This raises a number of questions:

  • When defining the charge density model, I assume what is put in is instead the number density of the dopants. Is this correct? Does it assume everything is fully ionized? Does the sign matter in the config file if n/p type is specified?
  • Is there an assumption of charge neutrality in the crystal when doing the calculations?
  • Would it be correct to approximate these p+ and n+ layers as bulk semiconductor material with high 'charge' density in your program? How does the depletion work here? As an example, if I explicitly put a small layer of p+ Si on top of an n type crystal and apply a negative voltage to the p+ side, it seems like the p+ layer is undepleted when looking at the point types (yellow vs green), although the bulk is depleted. [This is also a more general question as to what each number of the point type stands for.]

Thanks!

lmh91 commented

You can define an arbitrary charge density for your detector.
That't not documented yet. But we are currently working on that documentation
as we also change some internal naming (impurity vs charge density) to clarify that. (See #65 )

  • n-type and p-type is actually not taking into account anymore I believe and the signs of the charge density matters.
  • No there is no such assumption made. In the standard model, LinearChargeDensity, usually the whole detector is only assumed, e.g., n-type. Thus, there can not be a charge neutrality. As you said, at least for germanium detector, there is some heavily overdoped very thin p+-layer which is not taken into account through the LinearChargeDensity. But you can define your own density model where you do that.
  • This is somehow answered by the first point as there is no real difference between n-type and p-type. It only depends on the charge density model of the semiconductor. The depletion handling assumes that the BV is applied correctly.

I will post a small example how to define your own charge density here.
(Will also be soon in the documentation as well as a description how the depletion handling works.)

lmh91 commented

Here an example. Should work with the current master branch.

using Plots
using SolidStateDetectors

T = Float32
sim = Simulation(SSD_examples[:InvertedCoax])

calculate_electric_potential!(sim, max_refinements = 0)
plot(sim.ρ)

# The charge density model (actually it should be named impurity density model, we have to change this at some point)
# is part of the semiconductor object of the detector:
sim.detector.semiconductors[1].charge_density_model

# It can be overwritten by an custom density model.
# This must be subtype of AbstractChargeDensity model:

struct CustomChargeDensity{T} <: SolidStateDetectors.AbstractChargeDensity{T}
    # Define all the parameters for your own model here
    # e.g.:
    offset::T
    z_gradient::T
    r_gradient::T
end

# Create a model with arbitray parameters
ccdm = CustomChargeDensity{Float32}( -10^16, -10^18, -10^18) # meter not mm

# overwrite the predefined model
sim.detector.semiconductors[1].charge_density_model = ccdm

# We also need to define two methods for this density model:
# (So actually the model)
function SolidStateDetectors.get_charge_density(cdm::CustomChargeDensity{T}, pt::CylindricalPoint{T}) where {T}
    # This is the actually the impurity density: it will be multiplied by the elementary charge (in SSD)
    # Just an example:
    charge_density::T = cdm.offset
    charge_density += cdm.z_gradient * pt[3] # z coordinate
    charge_density += cdm.r_gradient * pt[1] # r coordinate
    # Note, that pt will be parsed to this function in SI units -> meter 
    return charge_density
end
# In case you use cartesian coordinates for the simulation just add this method:
function SolidStateDetectors.get_charge_density(cdm::CustomChargeDensity{T}, pt::CartesianPoint{T}) where {T}
    return SolidStateDetectors.get_charge_density(cdm, CylindricalPoint(pt))
end 


calculate_electric_potential!(sim, max_refinements = 2, depletion_handling=true)

plot(sim.point_types)
plot(sim.ρ)

# Plot the profile:
# We want to add this as a plot recipe in the future but is not yet implemented. 
rs = 0.0:1e-5:4e-2
charge_vec = similar(rs)
for ir in eachindex(rs)
    pt = CylindricalPoint{T}(rs[ir], 0, 1e-3)
    charge_vec[ir] = pt in sim.detector.semiconductors[1] ? 
        SolidStateDetectors.get_charge_density(sim.detector.semiconductors[1], pt) :
        0 
end
plot(rs, charge_vec, ylabel = "impurity density [1/m^3]", xlabel = "r [m]")

Nice, Lukas!

lmh91 commented

One more comment on the charge neutrality.
If you define such a charge density where you have n-type and p+-type (positive and negative charge regions),
then the detector would (should) only deplete such that charge neutrality is conserved as in non depleted regions the
charge density is actually set to 0 by SSD during the field calculation (I forgot to mention that.).

This actually might be a good test which should be added to the automated test of the Package.

Great, I'll take a look and get back to you!

lmh91 commented

Sorry, actually I forgot that I just had this on my to do list 😄

After the PR #98 is through, the bulk type is obsolete and the bulk type is determined locally through the charge density.

In the PR #98, there is an example of a 3D Simulation of a PN-Junction with overdoped n+ and p+ on both ends.

Really nice! I also tried a crude way just with constant IDP in blocks of geometry (which gave bogus last week), and it seems to be working as expected.

See also #271