SolverBase
compass.solvers.base.SolverBase는 COMPASS의 모든 전자기(EM) 솔버가 구현해야 하는 추상 기본 클래스(abstract base class)입니다. 러너(runner) 및 분석 모듈에서 사용하는 통일된 인터페이스를 정의합니다.
추상 인터페이스
class SolverBase(ABC):
def __init__(self, config: dict, device: str = "cpu"):매개변수:
config-- 솔버 설정 딕셔너리 (Hydra/YAML에서 제공).device-- 계산 장치:"cpu","cuda", 또는"mps".
속성(Properties)
name -> str
솔버 이름. config["name"] 또는 클래스 이름에서 파생됩니다.
solver_type -> str
솔버 유형: config["type"]에서 가져온 "rcwa" 또는 "fdtd".
추상 메서드
모든 솔버 백엔드는 다음 네 가지 메서드를 구현해야 합니다:
솔버 파이프라인: 추상 메서드
각 단계를 선택하여 메서드 시그니처와 데이터 타입을 확인하세요. RCWA와 FDTD 경로를 전환할 수 있습니다.
SolverFactory.create(name, config, device)setup_geometry
@abstractmethod
def setup_geometry(self, pixel_stack: PixelStack) -> None:솔버 비의존적인 PixelStack을 솔버의 내부 지오메트리 표현으로 변환합니다.
- RCWA 솔버는
pixel_stack.get_layer_slices()를 호출하여 2D 유전율 그리드를 가져옵니다. - FDTD 솔버는
pixel_stack.get_permittivity_grid()를 호출하여 3D 복셀 그리드를 가져옵니다.
setup_source
@abstractmethod
def setup_source(self, source_config: dict) -> None:여기 광원(excitation source)을 설정합니다 (파장, 각도, 편광).
run
@abstractmethod
def run(self) -> SimulationResult:시뮬레이션을 실행하고 표준화된 SimulationResult를 반환합니다.
get_field_distribution
@abstractmethod
def get_field_distribution(
self,
component: str, # "Ex", "Ey", "Ez", "|E|2"
plane: str, # "xy", "xz", "yz"
position: float, # 법선 축 방향 위치 (um)
) -> np.ndarray:시뮬레이션에서 2D 전계 슬라이스(field slice)를 추출합니다.
구상 메서드
validate_energy_balance
def validate_energy_balance(
self,
result: SimulationResult,
tolerance: float = 0.01,
) -> bool:시뮬레이션 결과에 대해 True를 반환합니다. 위반 시 경고를 로깅합니다.
run_timed
def run_timed(self) -> SimulationResult:run()에 타이밍 계측을 추가하여 래핑합니다. result.metadata에 다음 항목을 추가합니다:
runtime_seconds-- 벽시계 시간(wall-clock time)solver_name-- 솔버 이름 문자열solver_type--"rcwa"또는"fdtd"device-- 사용된 계산 장치
SolverFactory
compass.solvers.base.SolverFactory는 레지스트리 패턴을 사용하여 이름으로 솔버 인스턴스를 생성합니다.
SolverFactory.create
@classmethod
def create(cls, name: str, config: dict, device: str = "cpu") -> SolverBase:솔버 인스턴스를 생성합니다. 솔버 모듈이 아직 로드되지 않은 경우 지연 임포트(lazy import)를 수행합니다.
매개변수:
name-- 솔버 이름:"torcwa","grcwa","meent","fdtd_flaport"등.config-- 솔버 설정 딕셔너리.device-- 계산 장치.
예외 발생: 솔버 이름이 알 수 없고 해당 모듈을 임포트할 수 없는 경우 ValueError가 발생합니다.
SolverFactory.register
@classmethod
def register(cls, name: str, solver_class: type) -> None:솔버 클래스를 등록합니다. 솔버 모듈이 임포트될 때 자동으로 호출됩니다.
SolverFactory.list_solvers
@classmethod
def list_solvers(cls) -> list:등록된 모든 솔버의 이름을 반환합니다.
사용 가능한 솔버 백엔드
| 이름 | 모듈 | 유형 | 비고 |
|---|---|---|---|
torcwa | compass.solvers.rcwa.torcwa_solver | RCWA | PyTorch S-행렬 RCWA. 기본 백엔드이며 안정성을 위해 TF32 비활성화. |
grcwa | compass.solvers.rcwa.grcwa_solver | RCWA | JAX/NumPy RCWA. 교차 검증 기준점. 핵심 -- 제거 금지. |
meent | compass.solvers.rcwa.meent_solver | RCWA | 다중 백엔드 RCWA, 해석적 고유값 분해 지원. |
fmmax | compass.solvers.rcwa.fmmax_solver | RCWA | 4가지 정식화 선택 가능한 JAX 벡터 FMM. |
fdtd_flaport | compass.solvers.fdtd.flaport_solver | FDTD | PyTorch 2.5D FDTD, GPU + autograd. |
fdtdz | compass.solvers.fdtd.fdtdz_solver | FDTD | JAX 2D FDTD (z-불변); 2D 단면에 매우 빠름. |
fdtdx | compass.solvers.fdtd.fdtdx_solver | FDTD | JAX 3D FDTD, 멀티 GPU, 완전 미분 가능, MIT 라이선스. |
meep | compass.solvers.fdtd.meep_solver | FDTD | C++/Python 3D FDTD, 서브픽셀 평균화 및 수반(adjoint) 그래디언트 지원. |
tmm | compass.solvers.tmm.tmm_solver | TMM | 1D 평면 스택 전용, RCWA 대비 ~1000배 빠름. |
RCWA vs FDTD 솔버 비교
RCWA와 FDTD 솔버의 양자 효율(QE) 시뮬레이션 곡선을 비교합니다. 픽셀 피치와 솔버 매개변수를 조정하여 결과와 성능 변화를 확인하세요.
SimulationResult
모든 솔버에서 반환하는 표준화된 출력입니다:
@dataclass
class SimulationResult:
qe_per_pixel: Dict[str, np.ndarray] # 픽셀 이름 -> QE 스펙트럼
wavelengths: np.ndarray # 파장 배열 (um)
fields: Optional[Dict[str, FieldData]] # 파장별 전계 데이터
poynting: Optional[Dict[str, np.ndarray]]
reflection: Optional[np.ndarray] # R(lambda)
transmission: Optional[np.ndarray] # T(lambda)
absorption: Optional[np.ndarray] # A(lambda)
metadata: Dict # 타이밍, 솔버 정보FieldData
@dataclass
class FieldData:
Ex: Optional[np.ndarray] # 전계 x 성분 (3D 복소수)
Ey: Optional[np.ndarray]
Ez: Optional[np.ndarray]
x: Optional[np.ndarray] # 좌표 배열
y: Optional[np.ndarray]
z: Optional[np.ndarray]
@property
def E_intensity(self) -> Optional[np.ndarray]:
"""Compute |E|^2 = |Ex|^2 + |Ey|^2 + |Ez|^2."""커스텀 솔버 구현
새로운 솔버 백엔드를 추가하려면 다음과 같이 구현합니다:
from compass.solvers.base import SolverBase, SolverFactory
class MySolver(SolverBase):
def setup_geometry(self, pixel_stack):
self._pixel_stack = pixel_stack
# 내부 표현으로 변환...
def setup_source(self, source_config):
self._source_config = source_config
def run(self):
# 시뮬레이션 실행, SimulationResult 반환
...
def get_field_distribution(self, component, plane, position):
# 2D 전계 슬라이스 추출
...
# 등록
SolverFactory.register("my_solver", MySolver)