Skip to content

솔버 선택(Choosing a Solver)

COMPASS는 통합된 인터페이스를 통해 여러 전자기 솔버(Solver) 백엔드를 지원합니다. 이 가이드에서는 사용 가능한 솔버, 각 솔버의 사용 시점, 설정 방법, 수렴(Convergence) 검증 방법을 다룹니다.

이론 배경

각 방법의 물리 — RCWA와 FDTD가 실제로 무엇을 계산하고 어떤 가정을 사용하는지 — 는 RCWA 설명, FDTD 설명, RCWA vs FDTD를 참고하세요. 이 페이지는 운영 측면을 다룹니다: 어떤 솔버를 고르고, 어떻게 설정하며, 결과를 어떻게 검증할지.

사용 가능한 솔버

RCWA 솔버

이름라이브러리백엔드GPU상태
torcwatorcwaPyTorchCUDA주력, 권장
grcwagrcwaNumPy/JAXCUDA교차 검증용
meentmeentNumPy/JAX/PyTorchCUDA/CPU멀티 백엔드, 검증에 적합

FDTD 솔버

이름라이브러리백엔드GPU상태
fdtd_flaportfdtdPyTorchCUDA프로토타이핑

RCWA vs FDTD: 언제 사용할 것인가

트레이드오프 요약

기준RCWAFDTD
속도 (단일 파장)빠름 (0.1--2 s)느림 (30--120 s)
속도 (31점 스위프)~10 s (순차)~45 s (단일 광대역 실행)
메모리중간 (200--800 MB)높음 (1--4 GB)
주기적 구조네이티브 (블로흐 경계조건)주기적 경계조건 필요
곡면계단 근사계단 근사
분산 금속자연스러움 (파장별)드루드/로렌츠 피팅 필요
근접장 정확도원거리장에서 우수모든 곳에서 우수
수렴 파라미터푸리에 차수 N격자 간격 Δx
수치 안정성S-행렬 필요CFL 조건

솔버 성능과 정확도 트레이드오프를 인터랙티브하게 비교해 보십시오:

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%
상태:양호한 일치

RCWA가 우수한 경우

  • 표준 베이어 픽셀 QE 스위프(COMPASS의 주요 사용 사례)
  • 각도 응답 연구(θ, ϕ 변경만으로 가능)
  • 푸리에 차수 수렴 연구
  • 각 점이 독립적인 파라미터 스위프

FDTD가 유리한 경우

  • 비주기적 또는 유한 크기 구조
  • 단일 시뮬레이션(Simulation)에서의 광대역 응답
  • 구조 내부의 근접장 세부 정보가 중요한 경우
  • RCWA에 대한 교차 검증(Cross-Validation)

아래 다이어그램은 설정에서 시뮬레이션 결과까지 솔버 파이프라인을 통한 데이터 흐름을 보여줍니다:

솔버 파이프라인: 추상 메서드

각 단계를 선택하여 메서드 시그니처와 데이터 타입을 확인하세요. 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

솔버 설정 참조

torcwa (권장)

yaml
solver:
  name: "torcwa"
  type: "rcwa"
  params:
    fourier_order: [9, 9]       # Fourier harmonics [Nx, Ny]
    dtype: "complex64"           # complex64 or complex128
  stability:
    precision_strategy: "mixed"  # mixed | float32 | float64
    allow_tf32: false            # MUST be false for RCWA
    fourier_factorization: "li_inverse"  # li_inverse | naive
    energy_check:
      enabled: true
      tolerance: 0.02
      auto_retry_float64: true

핵심 파라미터: fourier_order

푸리에 차수(Fourier Order) N은 각 방향에서 유지되는 고조파의 수를 결정합니다. 전체 고조파 수는 (2Nx+1)×(2Ny+1)입니다. [9, 9]의 경우 19×19=361개의 모드가 됩니다. 레이어당 크기 2×361=722의 고유값 문제가 풀립니다.

차수모드행렬 크기일반적 실행시간정확도
[5, 5]121242x2420.1 s낮음
[9, 9]361722x7220.3 s양호
[13,13]7291458x14581.5 s높음
[17,17]12252450x24505.0 s매우 높음

핵심 파라미터: precision_strategy

다양한 정밀도 전략이 수치 정확도와 실행 시간에 어떤 영향을 미치는지 탐색해 보십시오:

수치 정밀도 비교: Float32 vs Float64

부동소수점 정밀도가 파동광학의 위상 계산 정확도에 미치는 영향을 확인하세요. 위상이 여러 주기에 걸쳐 누적되면 float32 오차는 증가하고 float64는 정확하게 유지됩니다.

Float32
cos(phase):1.0000105
sin(phase):0.0000105
오차 크기:1.50e-5
~7 유효 숫자
기계 엡실론: 1.2e-7
Float64
cos(phase):1.000000000000000
sin(phase):-0.000000000000005
오차 크기:2.79e-14
~16 유효 숫자
기계 엡실론: 2.2e-16
1e-161e-131e-101e-71e-41e-11510204060801000.5% QE 허용 오차위상 (2π 배수)절대 오차Float32Float64

"mixed" 전략(기본값)은 주 시뮬레이션을 complex64로 실행하되 고유값 분해를 complex128로 승격하여 CPU에서 실행합니다. 이는 속도와 안정성의 좋은 균형을 제공합니다.

mixed={float32 for layer setup, FFT, S-matrix productsfloat64 for eigendecomp (on CPU)

grcwa

yaml
solver:
  name: "grcwa"
  type: "rcwa"
  params:
    nG: 49                  # 총 평면파 수 (축별 차수가 아님)
    dtype: "complex128"     # grcwa defaults to float64

grcwa는 선택적 JAX 가속이 가능한 NumPy 기반 계산을 사용합니다. 기본적으로 complex128을 사용하며 속도를 희생하는 대신 torcwa보다 수치적으로 더 안정적인 경향이 있습니다. 교차 검증에 유용합니다.

grcwa 절단(truncation) 의미

grcwa는 평면파 수(nG)로 절단하는 반면, torcwa/meent/fmmax는 축별 차수 [m, m] → 총 (2m+1)²개를 사용합니다. nG: 49는 torcwa의 fourier_order: [49, 49]보다 훨씬 거친 설정이므로 숫자를 솔버 간에 그대로 복사하면 안 됩니다.

meent

yaml
solver:
  name: "meent"
  type: "rcwa"
  params:
    fourier_order: [9, 9]
    dtype: "complex64"
    backend: "torch"       # numpy | jax | torch

meent는 numpy (backend=0), jax (backend=1), torch (backend=2)의 세 가지 백엔드를 지원합니다. JAX 백엔드는 XLA 컴파일을 활용하여 성능을 높일 수 있습니다. meent는 내부적으로 나노미터를 사용하며, COMPASS 어댑터가 마이크로미터에서의 변환을 처리합니다.

fdtd_flaport

yaml
solver:
  name: "fdtd_flaport"
  type: "fdtd"
  params:
    grid_spacing: 0.02     # Grid cell size in um (20 nm)
    runtime: 200           # Simulation time in femtoseconds
    pml_layers: 15         # PML absorber thickness in cells
    dtype: "float64"

핵심 파라미터: grid_spacing

격자는 가장 작은 기하학적 특징과 가장 높은 굴절률 재료 내부의 가장 짧은 파장을 모두 분해해야 합니다. 400 nm에서 실리콘(n4)의 경우:

ΔxλminnmaxPPW=0.4004.0×10=0.010 um

여기서 PPW(파장당 포인트 수, Points Per Wavelength)는 정확도를 위해 최소 10이어야 합니다. 20 nm 격자가 대부분의 가시광 범위 시뮬레이션에 적합하지만, 10 nm은 메모리를 8배 더 사용하는 대신(3D) 더 나은 정확도를 제공합니다.

GPU vs CPU 고려사항

CUDA (NVIDIA GPU)

RCWA는 행렬 연산(FFT, 고유값 분해, S-행렬 곱)에서 GPU 가속의 혜택이 큽니다. 푸리에 차수 [7, 7] 이상에서 일반적으로 5--20배 속도 향상이 있습니다.

yaml
compute:
  backend: "cuda"
  gpu_id: 0

중요: Ampere 이상 GPU(RTX 30xx/40xx, A100)에서 TF32를 비활성화하십시오. TF32는 행렬 곱셈 연산에서 부동소수점 가수부를 23비트에서 10비트로 줄여 S-행렬 정확도를 치명적으로 저하시킵니다.

yaml
solver:
  stability:
    allow_tf32: false  # Always keep this false for RCWA

Apple Silicon (MPS)

PyTorch MPS 백엔드는 기본 텐서 연산에서 작동하지만 RCWA에 제한이 있습니다:

  • 일부 PyTorch 버전에서 복소수 지원이 불완전합니다
  • 고유값 분해가 자동으로 CPU로 폴백될 수 있습니다
  • RCWA 워크로드에서 성능은 일반적으로 CUDA보다 느립니다
yaml
compute:
  backend: "mps"

MPS 오류가 발생하면 먼저 CPU로 테스트하십시오.

CPU

모든 솔버는 GPU 의존성 없이 CPU에서 작동합니다. CPU 모드는 느리지만 완전히 기능하며 수치적으로 가장 안정적입니다.

yaml
compute:
  backend: "cpu"
  num_workers: 4

수렴 테스트

RCWA: 푸리에 차수 스위프

결과를 신뢰하기 전에 항상 수렴 여부를 검증하십시오. 푸리에 차수를 스위프하고 QE가 안정화되는지 확인합니다.

python
import numpy as np
from compass.solvers.base import SolverFactory

orders = range(5, 22, 2)
peak_green_qe = []

for N in orders:
    config["solver"]["params"]["fourier_order"] = [N, N]
    solver = SolverFactory.create("torcwa", config["solver"])
    solver.setup_geometry(pixel_stack)
    solver.setup_source({"wavelength": 0.55, "theta": 0.0,
                         "phi": 0.0, "polarization": "unpolarized"})
    result = solver.run()

    green_qe = np.mean([
        qe for name, qe in result.qe_per_pixel.items()
        if name.startswith("G")
    ])
    peak_green_qe.append(float(green_qe))
    print(f"Order {N:2d}: Green QE = {green_qe:.4f}")

# Check convergence: relative change < 1%
for i in range(1, len(peak_green_qe)):
    delta = abs(peak_green_qe[i] - peak_green_qe[i-1])
    print(f"  Order {list(orders)[i]}: delta = {delta:.5f}")

FDTD: 격자 간격 수렴

python
for spacing in [0.04, 0.02, 0.01]:
    config["solver"]["params"]["grid_spacing"] = spacing
    # ... run and compare QE

교차 솔버 검증

동일한 픽셀을 두 개의 솔버로 실행하고 QE 스펙트럼을 비교합니다:

python
from compass.visualization.qe_plot import plot_qe_comparison

ax_main, ax_diff = plot_qe_comparison(
    results=[torcwa_result, grcwa_result],
    labels=["torcwa", "grcwa"],
    show_difference=True,
    figsize=(10, 7),
)

동일한 푸리에 차수에서 잘 수렴된 시뮬레이션의 경우 절대 QE 1--2% 이내의 일치가 예상됩니다.

성능 벤치마크

2x2 베이어 단위 셀, 1.0 um 피치, 단일 파장, 수직 입사, NVIDIA RTX 4090 기준 일반적 수치:

솔버차수 / 격자실행시간GPU 메모리비고
torcwa (f32)[9, 9]0.3 s200 MB기본값, 빠름
torcwa (f64)[9, 9]0.6 s400 MB더 높은 정확도
torcwa (f32)[15, 15]2.1 s600 MB높은 정확도
grcwa (f64)[9, 9]0.5 s250 MB교차 검증
meent/torch (f32)[9, 9]0.4 s200 MB유사 성능
fdtd_flaport (20nm)--45 s2 GB광대역 가능
fdtd_flaport (10nm)--180 s8 GB높은 정확도

31점 파장 스위프(400--700 nm, 10 nm 간격):

  • RCWA (torcwa, 차수 9): 31 x 0.3 s = ~10 s 총 소요
  • FDTD (flaport, 20 nm): 1 광대역 실행 = ~45 s

RCWA는 좁은 스위프에서 유리합니다. FDTD는 매우 밀집된 파장 샘플링(>100점)에서 경쟁력이 있습니다.

빠른 시작 권장사항

사용 사례권장 솔버설정 참고사항
표준 QE 시뮬레이션torcwa차수 [9,9], 혼합 정밀도
논문 수준 결과torcwa차수 [15,15], float64
교차 검증torcwa + grcwa동일 차수, QE 비교
금속 격자 / 높은 대비 레이어torcwa 또는 meentLi 역규칙 인수분해
광대역 단일 샷fdtd_flaport10 nm 격자, 200 fs 실행시간
CPU 전용 환경meent (numpy)GPU 불필요

다음 단계