# 電流双極子(ダイポールアンテナ?)の放射パターンをプロットすためのシミュレーション
# 参考 https://meep.readthedocs.io/en/latest/Python_Tutorials/Near_to_Far_Field_Spectra/#radiation-pattern-of-an-antenna
# src_cmpt=mp.EzをExやEyにするだけでドキュメントと同じ画像を作成することができる


import meep as mp
import math

resolution = 50
sxy = 4
dpml = 1
# 計算する系のサイズ
cell = mp.Vector3(sxy+2*dpml,sxy+2*dpml,0)
pml_layers = [mp.PML(dpml)]

fcen = 1.0
df = 0.4
src_cmpt = mp.Ez


sources = [mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                     center=mp.Vector3(), #mp.Vector3()は引数を指定しなければすべて0
                     component=src_cmpt)
          ]
# 対称性が高いため,symmetriesを設定しておくと計算に使うメモリが減らせる
if src_cmpt == mp.Ex:
    symmetries = [mp.Mirror(mp.Y)]
elif src_cmpt == mp.Ey:
    symmetries = [mp.Mirror(mp.X)]
elif src_cmpt == mp.Ez:
    symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Y)]

sim = mp.Simulation(cell_size = cell,
                    resolution = resolution,
                    sources = sources,
                    symmetries = symmetries,
                    boundary_layers = pml_layers)

# 近接場から遠隔場のfluxを計算するための近接場領域の設定
# weight=-1 は光が入射する方向が軸と逆だから
nearfield_box = sim.add_near2far(fcen, 0, 1,
                                 mp.Near2FarRegion(mp.Vector3(y=0.5*sxy), size = mp.Vector3(x=sxy)),
                                 mp.Near2FarRegion(mp.Vector3(y=-0.5*sxy), size = mp.Vector3(x=sxy), weight = -1),
                                 mp.Near2FarRegion(mp.Vector3(x=0.5*sxy), size = mp.Vector3(y=sxy)),
                                 mp.Near2FarRegion(mp.Vector3(x=-0.5*sxy), size = mp.Vector3(y=sxy), weight = -1)
                                )
# 純粋な近接場の領域設定
flux_box = sim.add_flux(fcen, 0, 1,
                        mp.FluxRegion(mp.Vector3(y=0.5*sxy), size = mp.Vector3(x=sxy)),
                        mp.FluxRegion(mp.Vector3(y=-0.5*sxy), size = mp.Vector3(x=sxy), weight = -1),
                        mp.FluxRegion(mp.Vector3(x=0.5*sxy), size = mp.Vector3(y=sxy)),
                        mp.FluxRegion(mp.Vector3(x=-0.5*sxy), size = mp.Vector3(y=sxy), weight = -1)
                       )

sim.run(until_after_sources=mp.stop_when_fields_decayed(50, src_cmpt, mp.Vector3(), 1e-8))

flux = mp.get_fluxes(flux_box)
print("flux]:, {}".format(flux[0]))

# 1000 wavelengths out from the source
r = 1000 / fcen
# number of points in [0, 2*pi) range of angles
npts = 100

# nearfield_boxから遠隔場の座標を与えて遠隔場のfluxを入手し,標準出力している

for n in range(npts):
    ff = sim.get_farfield(nearfield_box, mp.Vector3(r*math.cos(2*math.pi*n/npts),
                                                    r*math.sin(2*math.pi*n/npts)))
    print("farfield:, {}, {}, ".format(n, 2*math.pi*n/npts), end='')
    print(",".join([str(f).strip('()').replace('j','i') for f in ff]))