74 lines
3.9 KiB
Python
74 lines
3.9 KiB
Python
"""
|
|
opto_physics_model.py - Physics Model for Optocoupler (Poisson solver)
|
|
"""
|
|
from devsim import (
|
|
node_solution, edge_from_node_model, edge_model, equation,
|
|
get_parameter, set_parameter,
|
|
interface_model, interface_equation,
|
|
contact_node_model, contact_equation,
|
|
node_model, element_from_edge_model
|
|
)
|
|
|
|
|
|
def setup_poisson(device, regions):
|
|
"""Setup Poisson equation for dielectric regions."""
|
|
for region in regions:
|
|
node_solution(device=device, region=region, name="Potential")
|
|
edge_from_node_model(device=device, region=region, node_model="Potential")
|
|
|
|
# E = -dV/dx
|
|
edge_model(device=device, region=region, name="ElectricField",
|
|
equation="(Potential@n0 - Potential@n1) * EdgeInverseLength")
|
|
edge_model(device=device, region=region, name="ElectricField:Potential@n0", equation="EdgeInverseLength")
|
|
edge_model(device=device, region=region, name="ElectricField:Potential@n1", equation="-EdgeInverseLength")
|
|
|
|
# D = eps * E
|
|
edge_model(device=device, region=region, name="DField", equation="Permittivity * ElectricField")
|
|
edge_model(device=device, region=region, name="DField:Potential@n0", equation="Permittivity * ElectricField:Potential@n0")
|
|
edge_model(device=device, region=region, name="DField:Potential@n1", equation="Permittivity * ElectricField:Potential@n1")
|
|
|
|
equation(device=device, region=region, name="PotentialEquation", variable_name="Potential",
|
|
edge_model="DField", variable_update="default")
|
|
|
|
try:
|
|
element_from_edge_model(device=device, region=region, edge_model="ElectricField")
|
|
except:
|
|
pass
|
|
|
|
|
|
def setup_interface(device, interface_name):
|
|
"""Setup potential continuity at interface."""
|
|
interface_model(device=device, interface=interface_name, name="continuousPotential", equation="Potential@r0 - Potential@r1")
|
|
interface_model(device=device, interface=interface_name, name="continuousPotential:Potential@r0", equation="1")
|
|
interface_model(device=device, interface=interface_name, name="continuousPotential:Potential@r1", equation="-1")
|
|
interface_equation(device=device, interface=interface_name, name="PotentialEquation",
|
|
interface_model="continuousPotential", type="continuous")
|
|
|
|
|
|
def setup_contact(device, contact_name, bias_value=0.0):
|
|
"""Setup Dirichlet boundary condition."""
|
|
bias_name = f"{contact_name}_bias"
|
|
set_parameter(device=device, name=bias_name, value=bias_value)
|
|
contact_node_model(device=device, contact=contact_name, name=f"{contact_name}_bc", equation=f"Potential - {bias_name}")
|
|
contact_node_model(device=device, contact=contact_name, name=f"{contact_name}_bc:Potential", equation="1")
|
|
contact_equation(device=device, contact=contact_name, name="PotentialEquation", node_model=f"{contact_name}_bc")
|
|
|
|
|
|
def setup_contacts(device, contact_map):
|
|
"""Setup Dirichlet BC for multiple contacts."""
|
|
for contact, region in contact_map.items():
|
|
bias_name = f"{contact}_bias"
|
|
set_parameter(device=device, name=bias_name, value=0.0)
|
|
contact_node_model(device=device, contact=contact, name=f"{contact}_bc", equation=f"Potential - {bias_name}")
|
|
contact_node_model(device=device, contact=contact, name=f"{contact}_bc:Potential", equation="1")
|
|
contact_equation(device=device, contact=contact, name="PotentialEquation",
|
|
node_model=f"{contact}_bc", edge_charge_model="DField")
|
|
|
|
|
|
def setup_virtual_contact(device, region, bias_name):
|
|
"""Setup virtual contact for entire region."""
|
|
node_model(device=device, region=region, name="virtual_contact_bc", equation=f"Potential - {bias_name}")
|
|
node_model(device=device, region=region, name="virtual_contact_bc:Potential", equation="1")
|
|
equation(device=device, region=region, name="PotentialEquation", variable_name="Potential",
|
|
node_model="virtual_contact_bc", variable_update="default")
|