Skip to content

SolverBase

compass.solvers.base.SolverBase는 COMPASS의 모든 전자기(EM) 솔버가 구현해야 하는 추상 기본 클래스(abstract base class)입니다. 러너(runner) 및 분석 모듈에서 사용하는 통일된 인터페이스를 정의합니다.

추상 인터페이스

python
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 경로를 전환할 수 있습니다.

setup_geometry(pixel_stack)
pixel_stack.get_layer_slices() 호출
setup_source(source_config)
레이어별 2D 유전율 그리드
run()
SimulationResult
get_field_distribution(...)
component, plane, position
SolverFactory.create(name, config, device)
torcwa
RCWA
grcwa
RCWA
meent
RCWA
fdtd_flaport
FDTD

setup_geometry

python
@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

python
@abstractmethod
def setup_source(self, source_config: dict) -> None:

여기 광원(excitation source)을 설정합니다 (파장, 각도, 편광).

run

python
@abstractmethod
def run(self) -> SimulationResult:

시뮬레이션을 실행하고 표준화된 SimulationResult를 반환합니다.

get_field_distribution

python
@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

python
def validate_energy_balance(
    self,
    result: SimulationResult,
    tolerance: float = 0.01,
) -> bool:

시뮬레이션 결과에 대해 R+T+A1을 검사합니다. 허용 오차(tolerance) 이내에서 에너지가 보존되면 True를 반환합니다. 위반 시 경고를 로깅합니다.

run_timed

python
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

python
@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

python
@classmethod
def register(cls, name: str, solver_class: type) -> None:

솔버 클래스를 등록합니다. 솔버 모듈이 임포트될 때 자동으로 호출됩니다.

SolverFactory.list_solvers

python
@classmethod
def list_solvers(cls) -> list:

등록된 모든 솔버의 이름을 반환합니다.

사용 가능한 솔버 백엔드

이름모듈유형비고
torcwacompass.solvers.rcwa.torcwa_solverRCWAPyTorch S-행렬 RCWA. 기본 백엔드이며 안정성을 위해 TF32 비활성화.
grcwacompass.solvers.rcwa.grcwa_solverRCWAJAX/NumPy RCWA. 교차 검증 기준점. 핵심 -- 제거 금지.
meentcompass.solvers.rcwa.meent_solverRCWA다중 백엔드 RCWA, 해석적 고유값 분해 지원.
fmmaxcompass.solvers.rcwa.fmmax_solverRCWA4가지 정식화 선택 가능한 JAX 벡터 FMM.
fdtd_flaportcompass.solvers.fdtd.flaport_solverFDTDPyTorch 2.5D FDTD, GPU + autograd.
fdtdzcompass.solvers.fdtd.fdtdz_solverFDTDJAX 2D FDTD (z-불변); 2D 단면에 매우 빠름.
fdtdxcompass.solvers.fdtd.fdtdx_solverFDTDJAX 3D FDTD, 멀티 GPU, 완전 미분 가능, MIT 라이선스.
meepcompass.solvers.fdtd.meep_solverFDTDC++/Python 3D FDTD, 서브픽셀 평균화 및 수반(adjoint) 그래디언트 지원.
tmmcompass.solvers.tmm.tmm_solverTMM1D 평면 스택 전용, RCWA 대비 ~1000배 빠름.

RCWA vs FDTD 솔버 비교

RCWA와 FDTD 솔버의 양자 효율(QE) 시뮬레이션 곡선을 비교합니다. 픽셀 피치와 솔버 매개변수를 조정하여 결과와 성능 변화를 확인하세요.

RCWA (Fourier 차수 = 9)
0%20%40%60%80%100%400500600700파장 (nm)QE (%)빨강초록파랑
FDTD (격자 = 20 nm)
0%20%40%60%80%100%400500600700파장 (nm)QE (%)빨강초록파랑
RCWA
예상 시간:137 ms
메모리:6 MB
주기 구조:
임의 형상:제한적
FDTD
예상 시간:188 ms
메모리:3 MB
주기 구조:
임의 형상:
일치도
최대 |Delta QE|:2.2%
평균 |Delta QE|:0.9%
상태:양호한 일치

SimulationResult

모든 솔버에서 반환하는 표준화된 출력입니다:

python
@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

python
@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."""

커스텀 솔버 구현

새로운 솔버 백엔드를 추가하려면 다음과 같이 구현합니다:

python
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)