Skip to content

FDTD 솔버(Solver) 실행

COMPASS는 flaport fdtd 백엔드를 통해 FDTD(유한차분 시간영역법, Finite-Difference Time-Domain) 시뮬레이션(Simulation)을 지원합니다. FDTD는 RCWA와 상호 보완적입니다. 단일 실행으로 광대역 결과를 제공하고, 임의의 지오메트리를 처리하며, 전체 시간 영역 장(Field) 진화를 제공하지만, 더 느리고 메모리 집약적입니다.

FDTD 사용 시점

다음이 필요한 경우 FDTD를 사용합니다:

  • 단일 시뮬레이션 실행에서의 광대역 스펙트럼 응답
  • 비주기적 또는 유한 크기 구조
  • 픽셀 스택(Pixel Stack) 내부의 근접장(Near-field) 분포 세부 정보
  • RCWA 결과에 대한 교차 검증(Cross-Validation)
  • 장 전파의 시간 영역 분석

표준 주기적 베이어 QE 스위프의 경우, RCWA(torcwa)가 더 빠릅니다. 상세한 비교는 솔버 선택을 참조하십시오.

FDTD 솔버 생성

python
from compass.solvers.base import SolverFactory

solver_config = {
    "name": "fdtd_flaport",
    "type": "fdtd",
    "params": {
        "grid_spacing": 0.02,   # 20 nm grid cells
        "runtime": 200,          # 200 femtoseconds
        "pml_layers": 15,        # 15-cell PML absorber
        "dtype": "float64",
    },
}

solver = SolverFactory.create("fdtd_flaport", solver_config, device="cuda")

격자 간격(Grid Spacing)

격자 간격(grid_spacing, 마이크로미터 단위)은 가장 중요한 FDTD 파라미터입니다. 가장 작은 기하학적 특징과 가장 높은 굴절률 재료 내부의 가장 짧은 파장을 모두 분해해야 합니다.

가시광 범위 실리콘 시뮬레이션의 경험 법칙:

Δxλminnmax×PPW

여기서 PPW(파장당 포인트 수, Points Per Wavelength)는 최소 10이어야 합니다. 400 nm에서 실리콘(n4.0)의 경우:

Δx0.4004.0×10=0.010 um (10 nm)

실제로 20 nm이면 대부분의 가시광 범위 시뮬레이션에 적합하며, 정확도와 리소스 사용 간의 좋은 트레이드오프를 제공합니다.

격자 간격 권장사항

격자 간격400nm/Si에서 PPW메모리 (2x2, 1um)실행시간정확도
40 nm2.5~250 MB~15 s낮음
20 nm5.0~2 GB~45 s적절
10 nm10.0~8 GB~180 s높음
5 nm20.0~64 GB~900 s매우 높음

메모리는 3D에서 O(1/Δx3)으로 스케일링되므로, 격자 간격을 절반으로 줄이면 메모리가 8배 증가합니다.

Interactive Yee Cell Viewer

Visualize the staggered Yee grid cell used in FDTD simulations. E-field components sit on cell edges, while H-field components sit on face centers.

Cells per wavelength (550 nm):5.5
Courant number S:0.5716
Stability limit (1/sqrt(3)):0.5774
Warning: Need 10+ cells/wavelength for accuracy
xyzExEyEzHxHyHz
Staggered Grid Concept

The Yee cell staggers E and H field components in both space and time. E-field components are located on the edges of the cell, while H-field components are located at the face centers.

This arrangement ensures that every curl finite-difference is centered, giving second-order accuracy. The spatial staggering by half a grid cell naturally satisfies the divergence-free conditions for both E and B fields.

For a grid spacing of 25 nm, the cell resolves 5.5 points per wavelength at 550 nm in silicon (n=4). A minimum of 10 cells per wavelength is recommended.

실행 시간(Runtime) 설정

runtime 파라미터(펨토초 단위)는 FDTD 시뮬레이션의 실행 시간을 제어합니다. 시뮬레이션은 다음을 위해 충분히 오래 실행되어야 합니다:

  1. 소스 펄스가 전체 구조를 통과할 때까지
  2. 모든 내부 반사가 충분히 감쇠할 때까지
  3. 모니터의 장이 정상 상태에 도달할 때까지
yaml
solver:
  name: "fdtd_flaport"
  type: "fdtd"
  params:
    grid_spacing: 0.02
    runtime: 200          # femtoseconds
    pml_layers: 15
    dtype: "float64"

200 fs의 실행 시간은 3 um 실리콘을 가진 대부분의 BSI 픽셀 구조에 충분합니다. 더 두꺼운 실리콘(>4 um)이나 높은 Q 공진을 가진 구조의 경우 300-500 fs로 증가하십시오.

서로 다른 실행 시간에서 결과를 비교하여 수렴을 검증할 수 있습니다:

python
import copy
from compass.runners.single_run import SingleRunner

runtimes = [100, 150, 200, 300]

for rt in runtimes:
    cfg = copy.deepcopy(config)
    cfg["solver"]["params"]["runtime"] = rt
    result = SingleRunner.run(cfg)
    avg_qe = sum(qe.mean() for qe in result.qe_per_pixel.values()) / len(result.qe_per_pixel)
    print(f"Runtime {rt} fs: avg QE = {avg_qe:.4f}")

PML 설정

PML(완전 정합층, Perfectly Matched Layer)은 시뮬레이션 경계에서 나가는 복사를 흡수합니다. pml_layers 파라미터는 격자 셀 수로 PML 영역의 두께를 설정합니다.

python
solver_config = {
    "name": "fdtd_flaport",
    "type": "fdtd",
    "params": {
        "grid_spacing": 0.02,
        "runtime": 200,
        "pml_layers": 15,    # 15 cells = 0.3 um at 20 nm grid
        "dtype": "float64",
    },
}

가이드라인:

  • 15셀이 기본값이며 대부분의 시뮬레이션에서 잘 작동합니다
  • 경계에서 허위 반사가 관측되면 20-25셀로 증가하십시오
  • 주기적 구조의 경우, PML은 z 방향(상/하)에만 적용됩니다. 측면 경계는 주기적 경계 조건을 사용합니다
  • PML은 시뮬레이션 도메인 크기에 추가되므로, 두꺼운 PML은 메모리 사용량을 증가시킵니다

광대역 vs 단일 파장

광대역 운용

FDTD는 소스가 시간 영역 펄스이기 때문에 단일 시뮬레이션에서 자연스럽게 광대역 결과를 생성합니다. 시뮬레이션 후, 기록된 장의 푸리에 변환(Fourier Transform)으로 모든 주파수에서의 스펙트럼 응답을 동시에 얻을 수 있습니다.

python
config = {
    "pixel": { ... },
    "solver": {
        "name": "fdtd_flaport",
        "type": "fdtd",
        "params": {"grid_spacing": 0.02, "runtime": 200, "pml_layers": 15},
    },
    "source": {
        "wavelength": {
            "mode": "sweep",
            "sweep": {"start": 0.40, "stop": 0.70, "step": 0.01},
        },
        "polarization": "unpolarized",
    },
    "compute": {"backend": "auto"},
}

result = SingleRunner.run(config)
# All 31 wavelength points come from a single FDTD run
print(f"Wavelengths: {len(result.wavelengths)} points")

이것이 밀집 스펙트럼 샘플링에서 FDTD의 핵심 장점입니다. 100점 파장 스위프는 10점 스위프와 거의 동일한 시간이 소요되지만, RCWA에서는 각 파장이 별도의 계산입니다.

단일 파장 운용

단일 파장의 경우, FDTD는 CW(연속파, Continuous Wave) 소스를 사용합니다. 단일 점에서는 RCWA보다 느리지만 전체 시간 영역 장 진화를 제공합니다:

python
config["source"] = {
    "wavelength": {"mode": "single", "value": 0.55},
    "polarization": "unpolarized",
}

result = SingleRunner.run(config)

격자 간격 수렴 테스트

항상 여러 격자 간격에서 실행하여 수렴(Convergence)을 검증하십시오:

python
import copy
import numpy as np
from compass.runners.single_run import SingleRunner

spacings = [0.04, 0.02, 0.01]
qe_results = []

for dx in spacings:
    cfg = copy.deepcopy(config)
    cfg["solver"]["params"]["grid_spacing"] = dx
    result = SingleRunner.run(cfg)
    green_qe = np.mean([
        qe for name, qe in result.qe_per_pixel.items()
        if name.startswith("G")
    ])
    qe_results.append(green_qe)
    print(f"Grid {dx*1000:.0f} nm: Green QE = {green_qe:.4f}")

# Check convergence
for i in range(1, len(qe_results)):
    delta = abs(qe_results[i] - qe_results[i-1])
    print(f"  {spacings[i]*1000:.0f} nm vs {spacings[i-1]*1000:.0f} nm: "
          f"delta = {delta:.5f}")

GPU 및 메모리 고려사항

flaport FDTD 솔버는 PyTorch 텐서를 사용하며 CUDA GPU 가속을 지원합니다. 주요 사항:

  • GPU 메모리: 20 nm 격자 간격의 2x2 단위 셀은 약 2 GB의 VRAM이 필요합니다. 10 nm에서는 약 8 GB로 증가합니다.
  • CPU 폴백: GPU 메모리가 부족하면 backend: "cpu"로 설정하십시오. CPU 실행은 5-10배 느리지만 시스템 RAM 이외의 메모리 한계가 없습니다.
  • dtype: 정확도를 위해 float64를 사용하십시오. float32는 메모리를 절약하지만 긴 시간 트레이스의 푸리에 변환에서 아티팩트가 발생할 수 있습니다.
yaml
compute:
  backend: "cuda"    # or "cpu" for memory-constrained systems
  gpu_id: 0

에너지 균형 검증(Energy Balance Validation)

모든 FDTD 실행 후 에너지 보존을 확인하십시오:

python
from compass.analysis.energy_balance import EnergyBalance

check = EnergyBalance.check(result, tolerance=0.02)
print(f"Valid: {check['valid']}, max error: {check['max_error']:.4f}")

FDTD 에너지 균형 오차는 공간 이산화로 인해 일반적으로 RCWA보다 큽니다(1-3% vs <1%). 오차가 3%를 초과하면 격자 간격을 줄이십시오.

다음 단계