JuliaPhysics / SolidStateDetectors.jl

Solid state detector field and charge drift simulation in Julia
Other
82 stars 32 forks source link

Depletion and general pn junctions #95

Closed leenderthayen closed 3 years ago

leenderthayen commented 4 years ago

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:

Thanks!

lmh91 commented 4 years ago

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 )

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 4 years ago

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]")
oschulz commented 4 years ago

Nice, Lukas!

lmh91 commented 4 years ago

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.

leenderthayen commented 4 years ago

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

lmh91 commented 3 years ago

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

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.

leenderthayen commented 3 years ago

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.

fhagemann commented 2 years ago

See also #271