Thank you Juan. I chose to go with the formulation in Selberherr:
I attempt to approximate the delta function through some function of iname_distance (thank you for the heads up):
def create_generation_recombination(device, region, generation_recombination_physics, variables):
"""
Bulk Shockley Read hall recombination model in terms of generation.
Differentiates between bulk and surfaces. There may be multiple different surfaces.
"""
if "traps_SRH" in generation_recombination_physics:
# Create {interface}_distance edge models, which evaluates to distance from the interface within the region
current_interfaces = [interface for interface in ds.get_interface_list(device=device) if region in interface]
for interface in current_interfaces:
ds.interface_normal_model(device=device, region=region, interface=interface)
# Create node_index@0 and node_index@n1 on each edge
ds.edge_from_node_model(device=device, region=region, node_model="node_index")
# Modify SRH to have different lifetimes on surface nodes and in bulk:
USRH_bulk = "(Electrons*Holes - NIE^2)/(taup*(Electrons + n1) + taun*(Holes + p1))"
USRH_surface = ""
for interface in current_interfaces:
# If any node is at interface, make USRH_bulk = 0
USRH_bulk += f" * (ifelse({interface}_distance > 0.0, 1, 0))"
# and evaluate its specific surface term
USRH_surface += f"+ (Electrons*Holes - NIE^2)/((Electrons + n1)/sp + (Holes + p1)/sn) * ifelse({interface}_distance > 0.0, 0, 1)"
# Usual treatment
USRH = USRH_bulk + " + " + USRH_surface
Gn = "-q * USRH"
Gp = "+q * USRH"
print(create_node_model(device, region, "USRH", USRH))
for i in ("Electrons", "Holes", "T"):
if i in variables:
create_node_model_derivative(device, region, "USRH", USRH, i)
print(ds.get_edge_model_list(device=device, region=region))
print(ds.get_node_model_list(device=device, region=region))
else:
Gn = 0
Gp = 0
create_node_model(device, region, "ElectronGeneration", Gn)
create_node_model(device, region, "HoleGeneration", Gp)
for i in ("Electrons", "Holes", "T"):
if i in variables:
create_node_model_derivative(device, region, "ElectronGeneration", Gn, i)
create_node_model_derivative(device, region, "HoleGeneration", Gp, i)
The prints show that the models are present:
print(ds.get_edge_model_list(device=device, region=region)) (e.g. we now have 'core___box_distance'
('DField', 'DField:Potential@n0', 'DField:Potential@n1', 'EField', 'EField:Potential@n0', 'EField:Potential@n1', 'EdgeCouple', 'EdgeInverseLength', 'EdgeLength', 'EdgeNodeVolume', 'Electrons@n0', 'Electrons@n1', 'Epar_n', 'Epar_n:Potential@n0', 'Epar_n:Potential@n1', 'Epar_p', 'Epar_p:Potential@n0', 'Epar_p:Potential@n1', 'Holes@n0', 'Holes@n1', 'Jn', 'Jn:Electrons@n0', 'Jn:Electrons@n1', 'Jn:Holes@n0', 'Jn:Holes@n1', 'Jn:Potential@n0', 'Jn:Potential@n1', 'Jn_arora_lf', 'Jn_arora_lf:Electrons@n0', 'Jn_arora_lf:Electrons@n1', 'Jn_arora_lf:Holes@n0', 'Jn_arora_lf:Holes@n1', 'Jn_arora_lf:Potential@n0', 'Jn_arora_lf:Potential@n1', 'Jp', 'Jp:Electrons@n0', 'Jp:Electrons@n1', 'Jp:Holes@n0', 'Jp:Holes@n1', 'Jp:Potential@n0', 'Jp:Potential@n1', 'Jp_arora_lf', 'Jp_arora_lf:Electrons@n0', 'Jp_arora_lf:Electrons@n1', 'Jp_arora_lf:Holes@n0', 'Jp_arora_lf:Holes@n1', 'Jp_arora_lf:Potential@n0', 'Jp_arora_lf:Potential@n1', 'Potential@n0', 'Potential@n1', 'V_t_edge', 'beta_n', 'beta_p', 'core___box_distance', 'core___box_normal_x', 'core___box_normal_y', 'core___clad_distance', 'core___clad_normal_x', 'core___clad_normal_y', 'core___slab_distance', 'core___slab_normal_x', 'core___slab_normal_y', 'edge_index', 'mu_arora_n_lf', 'mu_arora_p_lf', 'mu_n', 'mu_n:Electrons@n0', 'mu_n:Electrons@n1', 'mu_n:Holes@n0', 'mu_n:Holes@n1', 'mu_n:Potential@n0', 'mu_n:Potential@n1', 'mu_p', 'mu_p:Electrons@n0', 'mu_p:Electrons@n1', 'mu_p:Holes@n0', 'mu_p:Holes@n1', 'mu_p:Potential@n0', 'mu_p:Potential@n1', 'node_index@n0', 'node_index@n1', 'unitx', 'unity', 'vsat_n', 'vsat_p')
print(ds.get_node_model_list(device=device, region=region))
('Acceptors', 'AtContactNode', 'ContactSurfaceArea', 'DEG', 'Donors', 'EC', 'EC:Potential', 'EFN', 'EFN:Electrons', 'EFN:Potential', 'EFP', 'EFP:Holes', 'EFP:Potential', 'EG', 'EI', 'EI:Potential', 'EV', 'EV:Potential', 'Electrons', 'Holes', 'IntrinsicCharge', 'IntrinsicCharge:Potential', 'IntrinsicElectrons', 'IntrinsicElectrons:Potential', 'IntrinsicHoles', 'IntrinsicHoles:Potential', 'NC', 'NIE', 'NSurfaceNormal_x', 'NSurfaceNormal_y', 'NTOT', 'NV', 'NetDoping', 'NodeVolume', 'Potential', 'PotentialIntrinsicCharge', 'PotentialIntrinsicCharge:Potential', 'PotentialNodeCharge', 'PotentialNodeCharge:Electrons', 'PotentialNodeCharge:Holes', 'SurfaceArea', 'Tn', 'USRH', 'USRH:Electrons', 'USRH:Holes', 'V_t', 'coordinate_index', 'mu_arora_n_node', 'mu_arora_p_node', 'node_index', 'x', 'y', 'z')
This is evaluating to invalid right now, presumably because USRH is a node model, but the inname_distances are edge models
How would I use node_index@0 and node_index@n1 to transfer the edge quantities to the nodes?
Thanks!