Files
tcad-devsim/devsim/wisetop_opto/opto_device.py
T

148 lines
6.0 KiB
Python

"""
opto_device.py - Unified Device Setup for Optocoupler Simulation
"""
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from devsim import (
create_gmsh_mesh, add_gmsh_region, add_gmsh_interface, add_gmsh_contact,
finalize_mesh, create_device, get_region_list, get_interface_list,
set_parameter, get_node_model_values, get_edge_model_values,
solve, write_devices, element_from_edge_model
)
import opto_common
import opto_physics_model
class OptoDevice:
"""Unified device setup for optocoupler simulation."""
def __init__(self, name, dimension=2):
self.name = name
self.dimension = dimension
self.regions = []
self.mesh_file = None
def load_mesh(self, geo_file, mesh_file, force=False):
"""Generate and load mesh."""
opto_common.generate_mesh(geo_file, mesh_file, self.dimension, force)
self.mesh_file = mesh_file
print(f"--- Loading {self.dimension}D Mesh: {mesh_file} ---")
create_gmsh_mesh(mesh=self.name, file=mesh_file)
def setup_regions(self, region_material_map):
"""Add regions with material assignment."""
for region, material in region_material_map.items():
try:
add_gmsh_region(mesh=self.name, gmsh_name=region, region=region, material=material)
print(f" Region: {region}")
except Exception as e:
print(f" Warning: {region} - {e}")
def setup_interfaces(self, interface_list):
"""Add interfaces between regions."""
for iface_name, region0, region1 in interface_list:
try:
add_gmsh_interface(mesh=self.name, gmsh_name=iface_name, region0=region0, region1=region1, name=iface_name)
except:
pass
def setup_contacts(self, contact_list):
"""Add contacts for boundary conditions."""
for contact, region in contact_list:
try:
add_gmsh_contact(mesh=self.name, gmsh_name=contact, region=region, name=contact, material="metal")
print(f" Contact: {contact}")
except Exception as e:
print(f" Warning: {contact} - {e}")
def finalize(self):
"""Finalize mesh and create device."""
finalize_mesh(mesh=self.name)
create_device(mesh=self.name, device=self.name)
self.regions = list(get_region_list(device=self.name))
print(f"Regions: {self.regions}")
for region in self.regions:
eps_r = opto_common.PERMITTIVITY.get(region, 1.0)
set_parameter(device=self.name, region=region, name="Permittivity", value=eps_r * opto_common.eps_0)
opto_physics_model.setup_poisson(self.name, self.regions)
def setup_interface_physics(self):
"""Setup interface continuity conditions."""
interfaces = get_interface_list(device=self.name)
print(f"--- Interfaces: {len(interfaces)} ---")
for iface in interfaces:
try:
opto_physics_model.setup_interface(self.name, iface)
print(f" {iface} - OK")
except Exception as e:
print(f" {iface} - FAILED: {e}")
def apply_boundary_conditions(self, voltage_map):
"""Apply Dirichlet boundary conditions."""
print("--- Boundary Conditions ---")
for contact, voltage in voltage_map.items():
try:
opto_physics_model.setup_contact(self.name, contact, voltage)
print(f" {contact}: {voltage} V")
except Exception as e:
print(f" Warning: {contact} - {e}")
def apply_equipotential(self, region_voltage_map):
"""Apply equipotential constraints."""
print("--- Equipotential ---")
for region, (bias_name, voltage) in region_voltage_map.items():
try:
set_parameter(device=self.name, name=bias_name, value=voltage)
opto_physics_model.setup_virtual_contact(self.name, region, bias_name)
print(f" {region}: {voltage} V")
except Exception as e:
print(f" Warning: {region} - {e}")
def solve(self):
"""Solve Poisson equation."""
print(f"--- {self.dimension}D Poisson Solve ---")
solve(type="dc", absolute_error=1.0, relative_error=1e-10, maximum_iterations=30)
print(" Converged!")
def print_results(self):
"""Print simulation results."""
print("--- Results ---")
for region in self.regions:
try:
p = get_node_model_values(device=self.name, region=region, name="Potential")
if len(p) > 0:
print(f" {region}: {min(p):.1f} - {max(p):.1f} V")
except:
pass
print("--- E-field ---")
for region in ["region_dielectric", "region_led"]:
if region in self.regions:
try:
e = get_edge_model_values(device=self.name, region=region, name="ElectricField")
e_max = max(abs(min(e)), abs(max(e)))
print(f" {region}: E_max = {e_max:.0f} V/cm")
except:
pass
def create_element_models(self):
"""Create element models for 3D visualization."""
if self.dimension == 3:
print("--- 3D Element Models ---")
for region in self.regions:
try:
element_from_edge_model(device=self.name, region=region, edge_model="ElectricField")
except:
pass
def output(self, prefix):
"""Write output files."""
write_devices(file=f"{prefix}.msh", type="devsim")
write_devices(file=f"{prefix}.tec", type="tecplot")
print(f"Done: {prefix}.msh, {prefix}.tec")