15. 2D MHD ์†”๋ฒ„

15. 2D MHD ์†”๋ฒ„

ํ•™์Šต ๋ชฉํ‘œ

  • ์ฐจ์› ๋ถ„ํ• (Dimensional Splitting)๊ณผ ๋น„๋ถ„ํ• (Unsplit) ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ 1D MHD ๋ฐฉ๋ฒ•์„ 2D๋กœ ํ™•์žฅํ•˜๊ธฐ
  • 2D Cartesian ๊ทธ๋ฆฌ๋“œ์—์„œ ์œ ํ•œ ์ฒด์ ๋ฒ•(Finite Volume Method) ๊ตฌํ˜„ํ•˜๊ธฐ
  • Constrained Transport (CT)๋ฅผ ์ ์šฉํ•˜์—ฌ $\nabla \cdot B = 0$์„ ์ •ํ™•ํžˆ ๋ณด์กดํ•˜๊ธฐ
  • ์ž๊ธฐ์žฅ ์„ฑ๋ถ„์„ ์œ„ํ•œ ์—‡๊ฐˆ๋ฆฐ ๊ทธ๋ฆฌ๋“œ(Staggered Grid, Yee Mesh) ์‚ฌ์šฉํ•˜๊ธฐ
  • ๊ณ ์ฐจ ์žฌ๊ตฌ์„ฑ ๊ตฌํ˜„ํ•˜๊ธฐ: PLM, WENO
  • ๋ฒค์น˜๋งˆํฌ ๋ฌธ์ œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๊ธฐ: Orszag-Tang ์™€๋ฅ˜, Kelvin-Helmholtz ๋ถˆ์•ˆ์ •์„ฑ
  • Corner Transport Upwind (CTU) ๋ฐฉ๋ฒ• ์ดํ•ดํ•˜๊ธฐ

1. 2D MHD ์†Œ๊ฐœ

MHD ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ 1D์—์„œ 2D๋กœ ํ™•์žฅํ•˜๋ฉด ์ƒˆ๋กœ์šด ๊ณผ์ œ๋“ค์ด ๋„์ž…๋ฉ๋‹ˆ๋‹ค: ๋‹ค์ฐจ์› ํŒŒ๋™ ์ „ํŒŒ, ๊ธฐํ•˜ํ•™์  ์†Œ์Šค ํ•ญ, ๊ทธ๋ฆฌ๊ณ  ๋‹ค์ค‘ ์ฐจ์›์—์„œ $\nabla \cdot B = 0$์„ ๋ณด์กดํ•ด์•ผ ํ•˜๋Š” ์ค‘์š”ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

1.1 2D MHD ๋ฐฉ์ •์‹

2D Cartesian ์ขŒํ‘œ $(x, y)$์—์„œ ์ด์ƒ MHD ๋ฐฉ์ •์‹์€:

โˆ‚U/โˆ‚t + โˆ‚F/โˆ‚x + โˆ‚G/โˆ‚y = 0

์—ฌ๊ธฐ์„œ ๋ณด์กด ๋ณ€์ˆ˜๋Š”:

U = [ฯ, ฯv_x, ฯv_y, ฯv_z, B_x, B_y, B_z, E]แต€

$x$ ๋ฐฉํ–ฅ์˜ ํ”Œ๋Ÿญ์Šค:

F = [ฯv_x, ฯv_xยฒ + p_T - B_xยฒ/ฮผโ‚€, ฯv_x v_y - B_x B_y/ฮผโ‚€, ฯv_x v_z - B_x B_z/ฮผโ‚€,
     0, v_x B_y - v_y B_x, v_x B_z - v_z B_x,
     v_x(E + p_T) - B_x(vยทB)/ฮผโ‚€]แต€

๊ทธ๋ฆฌ๊ณ  ์œ ์‚ฌํ•˜๊ฒŒ $G$ ($y$ ๋ฐฉํ–ฅ์˜ ํ”Œ๋Ÿญ์Šค)๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด ์••๋ ฅ์€:

p_T = p + Bยฒ/(2ฮผโ‚€)

1.2 ๋ฐœ์‚ฐ ์ œ์•ฝ ์กฐ๊ฑด(Divergence Constraint)

์ž๊ธฐ์žฅ์€ ๋‹ค์Œ์„ ๋งŒ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

โˆ‡ ยท B = โˆ‚B_x/โˆ‚x + โˆ‚B_y/โˆ‚y = 0

1D์—์„œ๋Š” ์ด๊ฒƒ์ด $\partial B_x / \partial x = 0$์œผ๋กœ ์ถ•์†Œ๋˜์–ด, $B_x$๊ฐ€ ์ดˆ๊ธฐ์— ์ผ์ •ํ•˜๋ฉด ์ž๋™์œผ๋กœ ๋งŒ์กฑ๋ฉ๋‹ˆ๋‹ค. 2D์—์„œ๋Š” $\nabla \cdot B = 0$์„ ๋ณด์กดํ•˜๊ธฐ ์œ„ํ•ด ํŠน์ˆ˜ํ•œ ์ˆ˜์น˜์  ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

$\nabla \cdot B = 0$ ์œ„๋ฐ˜์˜ ๊ฒฐ๊ณผ: - ๋น„๋ฌผ๋ฆฌ์  ๋‹จ๊ทน์ž ํž˜ - ์ˆ˜์น˜์  ๋ถˆ์•ˆ์ •์„ฑ - ๋ถ€์ •ํ™•ํ•œ ํŒŒ๋™ ์†๋„์™€ ์ถฉ๊ฒฉํŒŒ ๊ตฌ์กฐ

1.3 2D์—์„œ์˜ ๊ณผ์ œ

  1. ๊ณ„์‚ฐ ๋น„์šฉ: $N_x \times N_y$ ์…€, ํƒ€์ž„์Šคํ…๋‹น $\mathcal{O}(N^2)$ ์—ฐ์‚ฐ
  2. ๋‹ค์ฐจ์› ํšจ๊ณผ: ์ฝ”๋„ˆ ๊ฒฐํ•ฉ(Corner Coupling), ํšก๋ฐฉํ–ฅ ํŒŒ๋™
  3. ๋ฐœ์‚ฐ ๋ณด์กด: ํŠน์ˆ˜ํ•œ ์ด์‚ฐํ™” ํ•„์š” (CT, divergence cleaning ๋“ฑ)
  4. CFL ์กฐ๊ฑด: ํƒ€์ž„์Šคํ…์ด 2D ํŒŒ๋™ ์ „ํŒŒ์— ์˜ํ•ด ์ œํ•œ๋จ

2. 2D ์œ ํ•œ ์ฒด์ ๋ฒ•(Finite Volume Method)

2.1 ์…€ ์ค‘์‹ฌ ์ด์‚ฐํ™”(Cell-Centered Discretization)

์˜์—ญ์„ ์ง์‚ฌ๊ฐํ˜• ์…€ $[x_{i-1/2}, x_{i+1/2}] \times [y_{j-1/2}, y_{j+1/2}]$๋กœ ๋‚˜๋ˆ•๋‹ˆ๋‹ค.

์…€ ํ‰๊ท  ๋ณด์กด ๋ณ€์ˆ˜:

U_{i,j} = (1/ฮ”xฮ”y) โˆซโˆซ U(x,y,t) dx dy

2.2 ๋ฐ˜์ด์‚ฐ(Semi-Discrete) ํ˜•์‹

์œ ํ•œ ์ฒด์  ์ด์‚ฐํ™”:

dU_{i,j}/dt = -(F_{i+1/2,j} - F_{i-1/2,j})/ฮ”x - (G_{i,j+1/2} - G_{i,j-1/2})/ฮ”y

์…€ ๋ฉด์—์„œ์˜ ํ”Œ๋Ÿญ์Šค๋Š” Riemann ์†”๋ฒ„(HLL, HLLD, Roe ๋“ฑ)๋กœ๋ถ€ํ„ฐ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

2.3 ์ฐจ์› ๋ถ„ํ• (Dimensional Splitting) (Strang Splitting)

์•„์ด๋””์–ด: 2D ์ง„ํ™”๋ฅผ ๊ต๋Œ€ํ•˜๋Š” 1D ์Šค์œ•์œผ๋กœ ๋ถ„ํ• .

ํ•˜๋‚˜์˜ ํƒ€์ž„์Šคํ… $\Delta t$์— ๋Œ€ํ•ด:

  1. $x$์—์„œ ๋ฐ˜ ์Šคํ…: $\Delta t / 2$ ๋™์•ˆ $\partial U / \partial t + \partial F / \partial x = 0$์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง„ํ™”
  2. $y$์—์„œ ์™„์ „ ์Šคํ…: $\Delta t$ ๋™์•ˆ $\partial U / \partial t + \partial G / \partial y = 0$์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง„ํ™”
  3. $x$์—์„œ ๋ฐ˜ ์Šคํ…: $\Delta t / 2$ ๋™์•ˆ $x$์—์„œ ๋‹ค์‹œ ์ง„ํ™”

์ด๊ฒƒ์ด Strang splitting์ž…๋‹ˆ๋‹ค (๊ฐ 1D ์Šคํ…์ด 2์ฐจ ์ •ํ™•๋„์ด๋ฉด ์‹œ๊ฐ„์— ๋Œ€ํ•ด 2์ฐจ ์ •ํ™•๋„).

์žฅ์ : - 1D Riemann ์†”๋ฒ„ ์žฌ์‚ฌ์šฉ - ๊ตฌํ˜„ ๊ฐ„๋‹จ

๋‹จ์ : - ๋น„๋“ฑ๋ฐฉ์„ฑ ์˜ค์ฐจ (๋ฐฉํ–ฅ์„ฑ ํŽธํ–ฅ) - ์ฐจ์› ๋ถ„ํ• ์— ๊ฑธ์ณ $\nabla \cdot B = 0$์„ ๋ณด์กดํ•˜๊ธฐ ์–ด๋ ค์›€

2.4 ๋น„๋ถ„ํ•  ๋ฐฉ๋ฒ•(Unsplit Methods)

Corner Transport Upwind (CTU) ๋ฐฉ๋ฒ•์€ ํšก๋ฐฉํ–ฅ ํ”Œ๋Ÿญ์Šค ๋ณด์ •์„ ํฌํ•จํ•˜์—ฌ ๋ชจ๋“  ๋ฐฉํ–ฅ์„ ๋™์‹œ์— ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์•Œ๊ณ ๋ฆฌ์ฆ˜ (๋‹จ์ˆœํ™”๋œ CTU):

  1. $x$์™€ $y$ ๋ฐฉํ–ฅ ๋ชจ๋‘์—์„œ ์…€ ๋ฉด์˜ ์ƒํƒœ ์žฌ๊ตฌ์„ฑ
  2. ๋ชจ๋“  ๋ฉด์—์„œ Riemann ๋ฌธ์ œ ํ’€๊ธฐ
  3. ํšก๋ฐฉํ–ฅ ํ”Œ๋Ÿญ์Šค ๋ณด์ • ๊ณ„์‚ฐ (์˜ˆ: ์ƒ๋ฅ˜ ์ฝ”๋„ˆ ์ƒํƒœ)
  4. ์ฝ”๋„ˆ ๊ฒฐํ•ฉ์„ ํฌํ•จํ•˜์—ฌ ๋ณด์กด ๋ณ€์ˆ˜ ์—…๋ฐ์ดํŠธ

CTU ๋ฐฉ๋ฒ•์€ ์™„์ „ํžˆ ๋‹ค์ฐจ์›์ ์ด๋ฉฐ ๋ฐฉํ–ฅ์„ฑ ํŽธํ–ฅ์„ ์ค„์ž…๋‹ˆ๋‹ค.

3. Constrained Transport (CT)

Constrained Transport๋Š” ์ž๊ธฐ์žฅ์„ ์œ„ํ•œ ์—‡๊ฐˆ๋ฆฐ ๊ทธ๋ฆฌ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  Faraday ๋ฒ•์น™์„ ์ ๋ถ„ ํ˜•์‹์œผ๋กœ ์ง„ํ™”์‹œํ‚ด์œผ๋กœ์จ $\nabla \cdot B = 0$์„ ๊ธฐ๊ณ„ ์ •๋ฐ€๋„๊นŒ์ง€ ๋ณด์กดํ•˜๋Š” ์ˆ˜์น˜ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

3.1 Yee Mesh (์—‡๊ฐˆ๋ฆฐ ๊ทธ๋ฆฌ๋“œ)

์…€ ์ค‘์‹ฌ ์–‘ ($(x_i, y_j)$์—์„œ): - $\rho, p, v_x, v_y, v_z, E$

๋ฉด ์ค‘์‹ฌ ์ž๊ธฐ์žฅ (์—‡๊ฐˆ๋ฆผ): - $B_x$๋Š” $(x_{i-1/2}, y_j)$ (์ˆ˜์ง $x$์ธ ๋ฉด) - $B_y$๋Š” $(x_i, y_{j-1/2})$ (์ˆ˜์ง $y$์ธ ๋ฉด) - $B_z$๋Š” ์…€ ์ค‘์‹ฌ $(x_i, y_j)$ (๋งŒ์•ฝ $B_z$๊ฐ€ ์กด์žฌํ•˜์ง€๋งŒ 2D์—์„œ ๋ฐœ์‚ฐ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Œ)

๋ชจ์„œ๋ฆฌ ์ค‘์‹ฌ ์ „๊ธฐ์žฅ: - $E_z$๋Š” $(x_i, y_j)$ (2D $xy$ ํ‰๋ฉด์—์„œ ์…€ ์ฝ”๋„ˆ)

3.2 ์ ๋ถ„ ํ˜•์‹์˜ Faraday ๋ฒ•์น™

Faraday ๋ฒ•์น™:

โˆ‚B/โˆ‚t = -โˆ‡ ร— E

2D์—์„œ ($B = (B_x, B_y, B_z)$์ด๊ณ  $E_z$๊ฐ€ ์œ ์ผํ•œ ๊ด€๋ จ ์ „๊ธฐ์žฅ ์„ฑ๋ถ„):

โˆ‚B_x/โˆ‚t = -โˆ‚E_z/โˆ‚y
โˆ‚B_y/โˆ‚t = โˆ‚E_z/โˆ‚x

์…€ ๋ฉด์— ๋Œ€ํ•ด ์ ๋ถ„:

d/dt โˆซ B_x dy = -[E_z(top) - E_z(bottom)]
d/dt โˆซ B_y dx = [E_z(right) - E_z(left)]

์ด๊ฒƒ์€ ์ดˆ๊ธฐ์— ์œ ์ง€๋˜๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ $\nabla \cdot B = 0$์„ ๋ณด์กดํ•ฉ๋‹ˆ๋‹ค.

3.3 ์ „๊ธฐ์žฅ ๊ณ„์‚ฐ

์ด์ƒ MHD์—์„œ ์ „๊ธฐ์žฅ:

E = -v ร— B

2D์—์„œ:

E_z = v_x B_y - v_y B_x

CT ์•Œ๊ณ ๋ฆฌ์ฆ˜:

  1. ์…€ ๋ฉด์—์„œ ๊ธฐ๋ณธ ๋ณ€์ˆ˜ ์žฌ๊ตฌ์„ฑ
  2. Riemann ๋ฌธ์ œ ํ’€๊ธฐ๋กœ ๋ฉด ์ค‘์‹ฌ ์†๋„์™€ ์ž๊ธฐ์žฅ ์–ป๊ธฐ
  3. ์…€ ๋ชจ์„œ๋ฆฌ์—์„œ ์ „๊ธฐ์žฅ ๊ณ„์‚ฐ ์ธ์ ‘ํ•œ ๋ฉด์œผ๋กœ๋ถ€ํ„ฐ ์ƒ๋ฅ˜(Upwinded) $v$์™€ $B$ ์‚ฌ์šฉ: E_z(i,j) = [v_x B_y - v_y B_x]_{i,j} ํ‰๊ท ํ™” ์ „๋žต: ์‚ฐ์ˆ  ํ‰๊ท , ์ƒ๋ฅ˜, Riemann ์†”๋ฒ„ ๊ธฐ๋ฐ˜

  4. ์ž๊ธฐ์žฅ ์—…๋ฐ์ดํŠธ ์ด์‚ฐ Faraday ๋ฒ•์น™ ์‚ฌ์šฉ: B_x(i-1/2, j)^{n+1} = B_x(i-1/2, j)^n - ฮ”t/ฮ”y [E_z(i,j+1/2) - E_z(i,j-1/2)] B_y(i, j-1/2)^{n+1} = B_y(i, j-1/2)^n + ฮ”t/ฮ”x [E_z(i+1/2,j) - E_z(i-1/2,j)]

3.4 ๋ฐœ์‚ฐ ์—†์Œ(Divergence-Free) ๋ณด์žฅ

์ด์‚ฐ ์—…๋ฐ์ดํŠธ๊ฐ€ Faraday ๋ฒ•์น™์˜ ์ ๋ถ„ ํ˜•์‹์œผ๋กœ๋ถ€ํ„ฐ ์œ ๋„๋˜์—ˆ์œผ๋ฏ€๋กœ, ์ด์‚ฐ ๋ฐœ์‚ฐ:

(โˆ‡ ยท B)_{i,j} = [B_x(i+1/2,j) - B_x(i-1/2,j)]/ฮ”x + [B_y(i,j+1/2) - B_y(i,j-1/2)]/ฮ”y

์€ ๊ธฐ๊ณ„ ์ •๋ฐ€๋„๊นŒ์ง€ ๋ณด์กด๋ฉ๋‹ˆ๋‹ค (์ดˆ๊ธฐ์— 0์ด๋ฉด).

4. ๊ณ ์ฐจ ์žฌ๊ตฌ์„ฑ(Higher-Order Reconstruction)

4.1 ๊ตฌ๊ฐ„ ์„ ํ˜• ๋ฐฉ๋ฒ•(Piecewise Linear Method, PLM)

2์ฐจ ๊ณต๊ฐ„ ์ •ํ™•๋„๋Š” ๊ฐ ์…€ ๋‚ด์—์„œ ์„ ํ˜•์œผ๋กœ ํ•ด๋ฅผ ์žฌ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

U(x) = U_i + ฯƒ_i (x - x_i)

์—ฌ๊ธฐ์„œ $\sigma_i$๋Š” ๊ธฐ์šธ๊ธฐ๋กœ, ์ด์›ƒ ์…€๋กœ๋ถ€ํ„ฐ ์ถ”์ •๋ฉ๋‹ˆ๋‹ค:

ฯƒ_i โ‰ˆ (U_{i+1} - U_{i-1}) / (2ฮ”x)  (์ค‘์‹ฌ ์ฐจ๋ถ„)

๊ธฐ์šธ๊ธฐ ์ œํ•œ(Slope Limiting): ๋ถˆ์—ฐ์† ๊ทผ์ฒ˜์—์„œ ํ—ˆ์œ„ ์ง„๋™์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ œํ•œ์ž ์ ์šฉ:

ฯƒ_i = minmod(ฯƒ_L, ฯƒ_C, ฯƒ_R)

์—ฌ๊ธฐ์„œ: - $\sigma_L = (U_i - U_{i-1}) / \Delta x$ - $\sigma_C = (U_{i+1} - U_{i-1}) / (2 \Delta x)$ - $\sigma_R = (U_{i+1} - U_i) / \Delta x$

minmod ์ œํ•œ์ž:

minmod(a, b, c) =
    min(|a|, |b|, |c|) * sign(a)  if sign(a) = sign(b) = sign(c)
    0                              otherwise

๊ธฐํƒ€ ์ œํ•œ์ž: MC (monotonized central), van Leer, superbee.

4.2 WENO (Weighted Essentially Non-Oscillatory)

WENO ๊ธฐ๋ฒ•์€ ์—ฌ๋Ÿฌ ์Šคํ…์‹ค์˜ ๊ฐ€์ค‘ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ์ฐจ ์ •ํ™•๋„(5์ฐจ ์ด์ƒ)๋ฅผ ๋‹ฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

WENO5 ์žฌ๊ตฌ์„ฑ (๋‹จ์ˆœํ™”):

5์  ์Šคํ…์‹ค $\{U_{i-2}, U_{i-1}, U_i, U_{i+1}, U_{i+2}\}$๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ธ ๊ฐœ์˜ 3์  ํ›„๋ณด ๋‹คํ•ญ์‹์„ ๊ตฌ์„ฑํ•œ ๋‹ค์Œ, ๋งค๋„๋Ÿฌ์›€ ๊ธฐ๋ฐ˜ ๊ฐ€์ค‘์น˜๋กœ ๋ธ”๋ Œ๋”ฉํ•˜์—ฌ $x_{i+1/2}$์—์„œ ์žฌ๊ตฌ์„ฑ๋œ ๊ฐ’์„ ์–ป์Šต๋‹ˆ๋‹ค.

์žฅ์ : - ๋งค๋„๋Ÿฌ์šด ์˜์—ญ์—์„œ ๊ณ ์ฐจ ์ •ํ™•๋„ - ๋ถˆ์—ฐ์† ๊ทผ์ฒ˜์—์„œ ๋น„์ง„๋™

๋‹จ์ : - ๊ณ„์‚ฐ์ ์œผ๋กœ ๋น„์Œˆ (ํฐ ์Šคํ…์‹ค, ๋น„์„ ํ˜• ๊ฐ€์ค‘์น˜) - ๋ณต์žกํ•œ ๊ตฌํ˜„

4.3 ํŠน์„ฑ ๋ณ€์ˆ˜ vs ๊ธฐ๋ณธ ๋ณ€์ˆ˜ ์žฌ๊ตฌ์„ฑ(Characteristic vs. Primitive Variable Reconstruction)

์žฌ๊ตฌ์„ฑ์€ ๋‹ค์Œ์—์„œ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: - ๊ธฐ๋ณธ ๋ณ€์ˆ˜ $(\rho, v_x, v_y, v_z, B_x, B_y, B_z, p)$: ๋” ๊ฐ„๋‹จํ•˜์ง€๋งŒ ๋น„๋ฌผ๋ฆฌ์  ์ƒํƒœ ์ƒ์„ฑ ๊ฐ€๋Šฅ - ๋ณด์กด ๋ณ€์ˆ˜ $U$: ๋ณด์กด์„ ๋ณด์žฅํ•˜์ง€๋งŒ ์ง„๋™ ์ƒ์„ฑ ๊ฐ€๋Šฅ - ํŠน์„ฑ ๋ณ€์ˆ˜ $W = L \cdot U$: ํŒŒ๋™ ๋ถ„๋ฆฌ, ๋ถˆ์—ฐ์† ํฌ์ฐฉ์— ์ตœ์ 

MHD์˜ ๊ฒฝ์šฐ, ํŠน์„ฑ ์žฌ๊ตฌ์„ฑ์ด ์„ ํ˜ธ๋˜์ง€๋งŒ Jacobian์˜ ๊ณ ์œ ๋ฒกํ„ฐ๋ฅผ ํ’€์–ด์•ผ ํ•˜๋ฏ€๋กœ (2D/3D์—์„œ ๋น„์Œˆ).

5. ์‹œ๊ฐ„ ์ ๋ถ„(Time Integration)

5.1 2D์—์„œ์˜ CFL ์กฐ๊ฑด

ํƒ€์ž„์Šคํ…์€ ๋‹ค์Œ์— ์˜ํ•ด ์ œํ•œ๋ฉ๋‹ˆ๋‹ค:

ฮ”t โ‰ค CFL * min(ฮ”x, ฮ”y) / max(|ฮป|)

์—ฌ๊ธฐ์„œ $\lambda$๋Š” ํŒŒ๋™ ์†๋„์ž…๋‹ˆ๋‹ค (๊ณ ์† ์ž๊ธฐ์ŒํŒŒ, Alfvรฉn, ์ €์† ์ž๊ธฐ์ŒํŒŒ, ์—”ํŠธ๋กœํ”ผ).

์•ˆ์ „์„ ์œ„ํ•ด ์ผ๋ฐ˜์ ์œผ๋กœ $CFL \approx 0.4-0.8$.

5.2 ์‹œ๊ฐ„ ๋‹จ๊ณ„ ๊ธฐ๋ฒ•(Time Stepping Schemes)

2์ฐจ Runge-Kutta (RK2):

U* = U^n + ฮ”t L(U^n)
U^{n+1} = 0.5 U^n + 0.5 U* + 0.5 ฮ”t L(U*)

์—ฌ๊ธฐ์„œ $L(U) = -(โˆ‚F/โˆ‚x + โˆ‚G/โˆ‚y)$๋Š” ๊ณต๊ฐ„ ์—ฐ์‚ฐ์ž์ž…๋‹ˆ๋‹ค.

3์ฐจ Runge-Kutta (RK3) (TVD-RK3):

U^{(1)} = U^n + ฮ”t L(U^n)
U^{(2)} = 3/4 U^n + 1/4 U^{(1)} + 1/4 ฮ”t L(U^{(1)})
U^{n+1} = 1/3 U^n + 2/3 U^{(2)} + 2/3 ฮ”t L(U^{(2)})

RK3๋Š” WENO ๊ธฐ๋ฒ•๊ณผ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

6. ๋ฒค์น˜๋งˆํฌ ๋ฌธ์ œ: Orszag-Tang ์™€๋ฅ˜

Orszag-Tang ์™€๋ฅ˜๋Š” ์ถฉ๊ฒฉํŒŒ, ์ „๋ฅ˜ ์‹œํŠธ, ๋ณต์žกํ•œ ์™€๋ฅ˜ ๊ตฌ์กฐ์˜ ํ˜•์„ฑ์„ ํŠน์ง•์œผ๋กœ ํ•˜๋Š” ํ‘œ์ค€ 2D MHD ํ…Œ์ŠคํŠธ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

6.1 ์ดˆ๊ธฐ ์กฐ๊ฑด

์˜์—ญ: ์ฃผ๊ธฐ ๊ฒฝ๊ณ„ ์กฐ๊ฑด์„ ๊ฐ–๋Š” $[0, 1] \times [0, 1]$.

ฯ = ฮณยฒ
p = ฮณ
v_x = -sin(2ฯ€y)
v_y = sin(2ฯ€x)
v_z = 0
B_x = -sin(2ฯ€y) / sqrt(4ฯ€)
B_y = sin(4ฯ€x) / sqrt(4ฯ€)
B_z = 0

์—ฌ๊ธฐ์„œ $\gamma = 5/3$ (๋‹จ์—ด ์ง€์ˆ˜).

์ด ์„ค์ •์€ $\beta \sim 1$ (ํ”Œ๋ผ์ฆˆ๋งˆ์™€ ์ž๊ธฐ ์••๋ ฅ์ด ๋น„์Šทํ•จ)์„ ๊ฐ€์ง€๋ฉฐ ๋‚œ๋ฅ˜ cascade๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

6.2 ์ง„ํ™”

์™€๋ฅ˜๊ฐ€ ์ง„ํ™”ํ•˜๋ฉด์„œ: - ์ถฉ๊ฒฉํŒŒ๊ฐ€ ํ˜•์„ฑ๋˜๊ณ  ์ƒํ˜ธ์ž‘์šฉ - ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ ์žฅ ์‚ฌ์ด์˜ ๊ฒฝ๊ณ„์—์„œ ์ „๋ฅ˜ ์‹œํŠธ ๋ฐœ๋‹ฌ - ์ž๊ธฐ ์žฌ๊ฒฐํ•ฉ ๋ฐœ์ƒ - ์™€๋„๊ฐ€ ๋” ์ž‘์€ ์Šค์ผ€์ผ๋กœ cascade

์ฃผ์š” ์ง„๋‹จ: - ๋ฐ€๋„ ์œค๊ณฝ: ์ถฉ๊ฒฉํŒŒ ๊ตฌ์กฐ ํ‘œ์‹œ - ์ž๊ธฐ์žฅ ์„ : ์žฌ๊ฒฐํ•ฉ๊ณผ ์œ„์ƒ ๋ณ€ํ™” ์„ค๋ช… - ์ „๋ฅ˜ ๋ฐ€๋„ $|j_z| = |\nabla \times B|_z$: ์ „๋ฅ˜ ์‹œํŠธ ์œ„์น˜

6.3 ์˜ˆ์ƒ ๊ฒฐ๊ณผ

$t \approx 0.5$์—์„œ ์ถฉ๊ฒฉํŒŒ์™€ ์™€๋ฅ˜์˜ ๋ณต์žกํ•œ ํŒจํ„ด์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ๋ฏธ์„ธ ๊ตฌ์กฐ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ๊ณ ํ•ด์ƒ๋„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜(512ยฒ ์ด์ƒ)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

7. MHD์—์„œ Kelvin-Helmholtz ๋ถˆ์•ˆ์ •์„ฑ

Kelvin-Helmholtz (KH) ๋ถˆ์•ˆ์ •์„ฑ์€ ์ƒ๋Œ€์ ์ธ ์ „๋‹จ ์šด๋™์— ์žˆ๋Š” ๋‘ ์œ ์ฒด ์‚ฌ์ด์˜ ๊ฒฝ๊ณ„๋ฉด์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

7.1 ์„ค์ •

์˜์—ญ: $x$์—์„œ ์ฃผ๊ธฐ, $y$์—์„œ ๋ฐ˜์‚ฌ ๋˜๋Š” ์ฃผ๊ธฐ์ธ $[0, 1] \times [-1, 1]$.

์†๋„ ์ „๋‹จ์ธต:

v_x(y) = -Vโ‚€ tanh(y / a)
v_y = ฮดvโ‚€ sin(2ฯ€x)  (์„ญ๋™)

์—ฌ๊ธฐ์„œ $V_0$๋Š” ์ „๋‹จ ์†๋„, $a$๋Š” ์ „๋‹จ์ธต ๋‘๊ป˜, $\delta v_0 \ll V_0$๋Š” ์„ญ๋™ ์ง„ํญ์ž…๋‹ˆ๋‹ค.

์ž๊ธฐ์žฅ ($x$ ๋ฐฉํ–ฅ์œผ๋กœ ๊ท ์ผ):

B_x = Bโ‚€
B_y = 0

7.2 ์„ ํ˜• ์•ˆ์ •์„ฑ ๋ถ„์„

์ž๊ธฐ์žฅ์ด ์—†๋Š” ๊ฒฝ์šฐ, ๋ชจ๋“œ $k$์— ๋Œ€ํ•œ KH ์„ฑ์žฅ๋ฅ ์€:

ฮณ_KH ~ k Vโ‚€ / 2  (์–‡์€ ์ „๋‹จ์ธต์— ๋Œ€ํ•ด)

์ž๊ธฐ์žฅ์ด ์žˆ์œผ๋ฉด, ์ž๊ธฐ ์žฅ๋ ฅ์ด ์งง์€ ํŒŒ์žฅ์„ ์•ˆ์ •ํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋ถ„์‚ฐ ๊ด€๊ณ„:

ฮณยฒ = kยฒ Vโ‚€ยฒ - kยฒ v_Aยฒ

์—ฌ๊ธฐ์„œ $v_A = B_0 / \sqrt{\mu_0 \rho}$๋Š” Alfvรฉn ์†๋„์ž…๋‹ˆ๋‹ค.

์•ˆ์ •ํ™” ์กฐ๊ฑด:

Bโ‚€ > sqrt(ฮผโ‚€ ฯ) Vโ‚€  (v_A > Vโ‚€)

$v_A > V_0$์ด๋ฉด, KH ๋ชจ๋“œ๊ฐ€ ์–ต์ œ๋ฉ๋‹ˆ๋‹ค.

7.3 ์ˆ˜์น˜ ์‹œ๋ฎฌ๋ ˆ์ด์…˜

์ดˆ๊ธฐ ์กฐ๊ฑด:

ฯ = 1
p = 1
v_x = -Vโ‚€ tanh(y / a)
v_y = ฮดvโ‚€ sin(2ฯ€x)
B_x = Bโ‚€
B_y = 0

์ „ํ˜•์ ์ธ ๋งค๊ฐœ๋ณ€์ˆ˜: $V_0 = 1$, $a = 0.1$, $\delta v_0 = 0.01$, $B_0 = 0$์—์„œ $2$.

๊ด€์ฐฐ: - $B_0 = 0$: ๊ณ ์ „์ ์ธ KH ๋กค ๋ฐœ๋‹ฌ - $B_0 = 0.5$: KH ์„ฑ์žฅ ๋А๋ ค์ง€์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ถˆ์•ˆ์ • - $B_0 = 2$: KH ์–ต์ œ, ์ž๊ธฐ ์žฅ๋ ฅ์ด ์•ˆ์ •ํ™”

8. Python ๊ตฌํ˜„: CT๋ฅผ ์‚ฌ์šฉํ•œ 2D MHD ์†”๋ฒ„

8.1 ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation

class MHD2D:
    def __init__(self, Nx, Ny, Lx, Ly, gamma=5/3):
        self.Nx, self.Ny = Nx, Ny
        self.Lx, self.Ly = Lx, Ly
        self.dx, self.dy = Lx / Nx, Ly / Ny
        self.gamma = gamma

        # Cell centers
        self.x = np.linspace(0.5*self.dx, Lx - 0.5*self.dx, Nx)
        self.y = np.linspace(0.5*self.dy, Ly - 0.5*self.dy, Ny)
        self.X, self.Y = np.meshgrid(self.x, self.y, indexing='ij')

        # Staggered grid for magnetic field (CT)
        # Bx at (i-1/2, j), By at (i, j-1/2)
        self.x_Bx = np.linspace(0, Lx, Nx+1)
        self.y_By = np.linspace(0, Ly, Ny+1)

        # Conserved variables (cell-centered)
        self.rho = np.ones((Nx, Ny))
        self.mx = np.zeros((Nx, Ny))
        self.my = np.zeros((Nx, Ny))
        self.mz = np.zeros((Nx, Ny))
        self.E = np.ones((Nx, Ny))

        # Magnetic field (staggered)
        self.Bx = np.zeros((Nx+1, Ny))  # Face-centered in x
        self.By = np.zeros((Nx, Ny+1))  # Face-centered in y
        self.Bz = np.zeros((Nx, Ny))    # Cell-centered (if needed)

        # Electric field (edge-centered)
        self.Ez = np.zeros((Nx+1, Ny+1))

        self.t = 0.0

    def primitive_variables(self):
        """Compute primitive variables from conserved."""
        vx = self.mx / self.rho
        vy = self.my / self.rho
        vz = self.mz / self.rho

        # Average magnetic field to cell centers
        Bx_cc = 0.5 * (self.Bx[:-1, :] + self.Bx[1:, :])
        By_cc = 0.5 * (self.By[:, :-1] + self.By[:, 1:])
        Bz_cc = self.Bz

        B2 = Bx_cc**2 + By_cc**2 + Bz_cc**2
        p = (self.gamma - 1) * (self.E - 0.5 * self.rho * (vx**2 + vy**2 + vz**2) - 0.5 * B2)

        return self.rho, vx, vy, vz, p, Bx_cc, By_cc, Bz_cc

    def compute_dt(self, CFL=0.4):
        """Compute timestep based on CFL condition."""
        rho, vx, vy, vz, p, Bx, By, Bz = self.primitive_variables()

        # Fast magnetosonic speed
        cs = np.sqrt(self.gamma * p / rho)
        va = np.sqrt((Bx**2 + By**2 + Bz**2) / rho)
        cf = np.sqrt(cs**2 + va**2)

        dt_x = self.dx / np.max(np.abs(vx) + cf)
        dt_y = self.dy / np.max(np.abs(vy) + cf)

        return CFL * min(dt_x, dt_y)

    def check_divergence(self):
        """Check divergence of B (should be ~0)."""
        div_B = (self.Bx[1:, :] - self.Bx[:-1, :]) / self.dx + \
                (self.By[:, 1:] - self.By[:, :-1]) / self.dy
        return np.max(np.abs(div_B))

8.2 ์ž๊ธฐ์žฅ์„ ์œ„ํ•œ CT ์—…๋ฐ์ดํŠธ

def update_magnetic_field_CT(self):
    """Update magnetic field using Constrained Transport."""
    # Compute electric field Ez at cell corners (edges in 2D)
    # Ez = vx * By - vy * Bx

    # Need velocities and B fields at corners
    # Simple averaging (can be improved with Riemann solver values)

    # Average vx to y-edges
    vx_avg_y = 0.5 * (self.mx[:-1, :] / self.rho[:-1, :] + self.mx[1:, :] / self.rho[1:, :])
    vx_avg_y = np.pad(vx_avg_y, ((1,0), (0,0)), mode='wrap')  # Periodic

    # Average vy to x-edges
    vy_avg_x = 0.5 * (self.my[:, :-1] / self.rho[:, :-1] + self.my[:, 1:] / self.rho[:, 1:])
    vy_avg_x = np.pad(vy_avg_x, ((0,0), (1,0)), mode='wrap')

    # Average Bx to corners (from faces)
    Bx_corner = 0.5 * (self.Bx[:, :-1] + self.Bx[:, 1:])
    Bx_corner = np.pad(Bx_corner, ((0,0), (0,1)), mode='wrap')

    # Average By to corners (from faces)
    By_corner = 0.5 * (self.By[:-1, :] + self.By[1:, :])
    By_corner = np.pad(By_corner, ((0,1), (0,0)), mode='wrap')

    # Compute Ez at corners
    # This is simplified; production codes use Riemann solver at faces
    self.Ez = vx_avg_y * By_corner - vy_avg_x * Bx_corner

    # Update Bx using Ez (discrete Faraday's law)
    # โˆ‚Bx/โˆ‚t = -โˆ‚Ez/โˆ‚y
    dt = self.compute_dt()
    self.Bx[:, :] -= dt / self.dy * (self.Ez[:, 1:] - self.Ez[:, :-1])

    # Update By
    # โˆ‚By/โˆ‚t = โˆ‚Ez/โˆ‚x
    self.By[:, :] += dt / self.dx * (self.Ez[1:, :] - self.Ez[:-1, :])

8.3 ์™„์ „ํ•œ 2D MHD ์†”๋ฒ„ (๋‹จ์ˆœํ™”)

Riemann ์†”๋ฒ„, CT, ๊ณ ์ฐจ ์žฌ๊ตฌ์„ฑ์„ ๊ฐ–์ถ˜ ์™„์ „ํ•œ 2D MHD ์†”๋ฒ„์˜ ๋ณต์žก์„ฑ ๋•Œ๋ฌธ์—, ์—ฌ๊ธฐ์„œ๋Š” ๊ฐœ๋…์  ๊ณจ๊ฒฉ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. Athena, FLASH, Pluto์™€ ๊ฐ™์€ ์ƒ์‚ฐ ์ฝ”๋“œ๋Š” ์ด๊ฒƒ์„ ์ˆ˜์ฒœ ์ค„๋กœ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ˆœํ™”๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜:

def step(self, dt):
    """Single timestep using operator splitting."""
    # Step 1: Half step in x direction
    self.step_x(dt / 2)

    # Step 2: Full step in y direction
    self.step_y(dt)

    # Step 3: Half step in x direction
    self.step_x(dt / 2)

    # Update magnetic field using CT
    self.update_magnetic_field_CT()

    self.t += dt

def step_x(self, dt):
    """1D sweep in x direction (simplified)."""
    # For each j, solve 1D Riemann problems along x
    for j in range(self.Ny):
        # Extract 1D slice
        rho_1d = self.rho[:, j]
        mx_1d = self.mx[:, j]
        # ... (other variables)

        # Reconstruct, solve Riemann problem, update
        # (Reuse 1D MHD solver)

        # Update conserved variables
        # self.rho[:, j] = ...
        pass

def step_y(self, dt):
    """1D sweep in y direction."""
    # Similar to step_x but along y
    pass

์ฐธ๊ณ : ๊ฒฌ๊ณ ํ•œ 2D MHD ์†”๋ฒ„๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ๋‹ค์Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค: - 1D Riemann ์†”๋ฒ„ (HLL, HLLD ๋“ฑ) - ์žฌ๊ตฌ์„ฑ (PLM, WENO) - Riemann ์†”๋ฒ„ ๋ฉด ์ƒํƒœ๋กœ๋ถ€ํ„ฐ CT ์ „๊ธฐ์žฅ ๊ณ„์‚ฐ - ๊ฒฝ๊ณ„ ์กฐ๊ฑด - ์†Œ์Šค ํ•ญ (์ค‘๋ ฅ ๋“ฑ, ํ•ด๋‹น๋˜๋Š” ๊ฒฝ์šฐ)

๊ต์œก ๋ชฉ์ ์œผ๋กœ Orszag-Tang ์™€๋ฅ˜ ์„ค์ •๊ณผ ๊ฐ„๋‹จํ•œ forward-Euler ์—…๋ฐ์ดํŠธ๋ฅผ ์‹œ์—ฐํ•ฉ๋‹ˆ๋‹ค.

8.4 Orszag-Tang ์™€๋ฅ˜ ์„ค์ •

def init_orszag_tang(mhd, gamma=5/3):
    """Initialize Orszag-Tang vortex."""
    X, Y = mhd.X, mhd.Y

    # Density and pressure
    mhd.rho[:, :] = gamma**2
    p = gamma * np.ones_like(mhd.rho)

    # Velocity
    vx = -np.sin(2 * np.pi * Y)
    vy = np.sin(2 * np.pi * X)
    vz = np.zeros_like(vx)

    mhd.mx = mhd.rho * vx
    mhd.my = mhd.rho * vy
    mhd.mz = mhd.rho * vz

    # Magnetic field (staggered grid)
    # Bx at (i-1/2, j)
    X_Bx, Y_Bx = np.meshgrid(mhd.x_Bx, mhd.y, indexing='ij')
    mhd.Bx[:, :] = -np.sin(2 * np.pi * Y_Bx) / np.sqrt(4 * np.pi)

    # By at (i, j-1/2)
    X_By, Y_By = np.meshgrid(mhd.x, mhd.y_By, indexing='ij')
    mhd.By[:, :] = np.sin(4 * np.pi * X_By) / np.sqrt(4 * np.pi)

    # Bz (cell-centered, zero)
    mhd.Bz[:, :] = 0.0

    # Total energy
    Bx_cc = 0.5 * (mhd.Bx[:-1, :] + mhd.Bx[1:, :])
    By_cc = 0.5 * (mhd.By[:, :-1] + mhd.By[:, 1:])
    B2 = Bx_cc**2 + By_cc**2

    mhd.E = p / (gamma - 1) + 0.5 * mhd.rho * (vx**2 + vy**2 + vz**2) + 0.5 * B2

# Initialize
Nx, Ny = 128, 128
mhd = MHD2D(Nx, Ny, Lx=1.0, Ly=1.0, gamma=5/3)
init_orszag_tang(mhd)

print(f"Orszag-Tang vortex initialized on {Nx}ร—{Ny} grid")
print(f"Initial div(B) max: {mhd.check_divergence():.3e}")

8.5 ๊ฐ„๋‹จํ•œ Forward Euler ์—…๋ฐ์ดํŠธ (์‹œ์—ฐ์šฉ)

def simple_update(mhd, dt):
    """
    Simplified forward Euler update (NOT recommended for production).
    For demonstration only.
    """
    rho, vx, vy, vz, p, Bx, By, Bz = mhd.primitive_variables()

    # Compute fluxes (very simplified, ignoring Riemann solver)
    # This will NOT capture shocks correctly!

    # Flux in x direction (at i+1/2, j)
    Fx_rho = mhd.mx  # rho * vx
    # ... (other flux components)

    # Update conserved variables (forward Euler, very crude)
    # drho/dt = -(dFx/dx + dFy/dy)

    # For proper implementation, use Riemann solver at each face
    # This is just a placeholder

    # Update magnetic field via CT
    mhd.update_magnetic_field_CT()

    mhd.t += dt

# Note: This is NOT a working solver, just a skeleton
# For actual simulation, use established codes or implement full Riemann solver

8.6 ์‹œ๊ฐํ™”

def plot_orszag_tang(mhd):
    """Plot density and magnetic field."""
    rho, vx, vy, vz, p, Bx, By, Bz = mhd.primitive_variables()

    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

    # Density
    im1 = ax1.contourf(mhd.X, mhd.Y, rho, levels=50, cmap='viridis')
    ax1.set_title(f'Density at t = {mhd.t:.3f}', fontsize=14)
    ax1.set_xlabel('x', fontsize=12)
    ax1.set_ylabel('y', fontsize=12)
    plt.colorbar(im1, ax=ax1)

    # Magnetic field lines
    ax2.contourf(mhd.X, mhd.Y, np.sqrt(Bx**2 + By**2), levels=50, cmap='plasma')
    ax2.streamplot(mhd.X.T, mhd.Y.T, Bx.T, By.T, color='white', linewidth=0.5, density=1.5)
    ax2.set_title(f'Magnetic Field at t = {mhd.t:.3f}', fontsize=14)
    ax2.set_xlabel('x', fontsize=12)
    ax2.set_ylabel('y', fontsize=12)

    plt.tight_layout()
    plt.savefig(f'orszag_tang_t{mhd.t:.3f}.png', dpi=150)
    plt.show()

plot_orszag_tang(mhd)

8.7 Kelvin-Helmholtz ๋ถˆ์•ˆ์ •์„ฑ ์„ค์ •

def init_kelvin_helmholtz(mhd, V0=1.0, a=0.1, dv=0.01, B0=0.0):
    """Initialize Kelvin-Helmholtz instability."""
    X, Y = mhd.X, mhd.Y

    # Density (uniform)
    mhd.rho[:, :] = 1.0

    # Pressure (uniform)
    p = 1.0 * np.ones_like(mhd.rho)

    # Velocity shear
    vx = -V0 * np.tanh(Y / a)
    vy = dv * np.sin(2 * np.pi * X)
    vz = np.zeros_like(vx)

    mhd.mx = mhd.rho * vx
    mhd.my = mhd.rho * vy
    mhd.mz = mhd.rho * vz

    # Magnetic field (uniform in x)
    mhd.Bx[:, :] = B0
    mhd.By[:, :] = 0.0
    mhd.Bz[:, :] = 0.0

    # Total energy
    Bx_cc = 0.5 * (mhd.Bx[:-1, :] + mhd.Bx[1:, :])
    By_cc = 0.5 * (mhd.By[:, :-1] + mhd.By[:, 1:])
    B2 = Bx_cc**2 + By_cc**2

    mhd.E = p / (mhd.gamma - 1) + 0.5 * mhd.rho * (vx**2 + vy**2) + 0.5 * B2

# Initialize KH instability
mhd_kh = MHD2D(Nx=256, Ny=256, Lx=1.0, Ly=2.0, gamma=5/3)
init_kelvin_helmholtz(mhd_kh, V0=1.0, a=0.1, dv=0.01, B0=0.5)

print(f"Kelvin-Helmholtz initialized: V0=1.0, B0=0.5")
print(f"Alfvรฉn speed: vA = {0.5 / np.sqrt(1.0):.2f} (should stabilize if vA > V0)")

8.8 ์ƒ์‚ฐ๊ธ‰ ์ฝ”๋“œ

์‹ค์ œ ์—ฐ๊ตฌ๋ฅผ ์œ„ํ•ด์„œ๋Š” ํ™•๋ฆฝ๋œ MHD ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”:

Athena++: https://github.com/PrincetonUniversity/athena - C++, ํ˜„๋Œ€์  AMR (adaptive mesh refinement) - MHD, radiation, GR ์˜ต์…˜ - ๋ฐœ์‚ฐ ์—†๋Š” B๋ฅผ ์œ„ํ•œ CT

PLUTO: http://plutocode.ph.unito.it/ - ๋ชจ๋“ˆํ˜•, ๋‹ค์–‘ํ•œ ๋ฌผ๋ฆฌ ๋ชจ๋“ˆ ์ง€์› - MHD, ์ƒ๋Œ€๋ก ์  MHD, radiation - ๋‹ค์ค‘ Riemann ์†”๋ฒ„, CT

FLASH: https://flash.rochester.edu/ - ๋Œ€๊ทœ๋ชจ ์ฒœ์ฒด๋ฌผ๋ฆฌํ•™ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ - AMR, MHD, ์œ ์ฒด์—ญํ•™ - ์ดˆ์‹ ์„ฑ, ๋ณ„ ํ˜•์„ฑ์— ๋„๋ฆฌ ์‚ฌ์šฉ

์˜ˆ์ œ: Orszag-Tang ์™€๋ฅ˜๋ฅผ ์œ„ํ•œ Athena ์‹คํ–‰:

# Athena input file (athinput.orszag_tang)
<problem>
problem_id = OrszagTang
gamma = 1.666667

<mesh>
nx1 = 256
nx2 = 256
x1min = 0.0
x1max = 1.0
x2min = 0.0
x2max = 1.0
ix1_bc = periodic
ox1_bc = periodic
ix2_bc = periodic
ox2_bc = periodic

<hydro>
evolution = mhd

<time>
tlim = 0.5

์‹คํ–‰:

./athena -i athinput.orszag_tang

9. ๊ณ ๊ธ‰ ์ฃผ์ œ

9.1 Adaptive Mesh Refinement (AMR)

AMR์€ ๊ด€์‹ฌ ์˜์—ญ(์ถฉ๊ฒฉํŒŒ, ์ „๋ฅ˜ ์‹œํŠธ)์—์„œ ๊ทธ๋ฆฌ๋“œ๋ฅผ ๋™์ ์œผ๋กœ ์ •์ œํ•˜๊ณ  ๋‹ค๋ฅธ ๊ณณ์—์„œ๋Š” ์กฐ๋Œ€ํ™”ํ•˜์—ฌ ๊ณ„์‚ฐ ๋น„์šฉ์„ ์ ˆ๊ฐํ•ฉ๋‹ˆ๋‹ค.

MHD AMR์˜ ๊ณผ์ œ: - ์ •์ œ ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด $\nabla \cdot B = 0$ ๋ณด์กด - ์—‡๊ฐˆ๋ฆฐ ์žฅ์— ๋Œ€ํ•œ prolongation๊ณผ restriction ์—ฐ์‚ฐ์ž

ํ•ด๊ฒฐ์ฑ…: - ์กฐ๋Œ€-๋ฏธ์„ธ ๊ฒฝ๊ณ„์—์„œ ํ”Œ๋Ÿญ์Šค ๋ณด์ • - ๋ฐœ์‚ฐ ๋ณด์กด prolongation (์˜ˆ: Balsara ๋ฐฉ๋ฒ•)

9.2 ๋ฐœ์‚ฐ ์ฒญ์†Œ(Divergence Cleaning)

CT์˜ ๋Œ€์•ˆ: 0์ด ์•„๋‹Œ $\nabla \cdot B$๋ฅผ ํ—ˆ์šฉํ•˜๋˜ ๊ฐ์‡  ๋ฉ”์ปค๋‹ˆ์ฆ˜ ์ถ”๊ฐ€.

์Œ๊ณก์„  ๋ฐœ์‚ฐ ์ฒญ์†Œ (Dedner et al. 2002):

๋ณด์กฐ ์Šค์นผ๋ผ ์žฅ $\psi$๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ง„ํ™”:

โˆ‚B/โˆ‚t + โˆ‡ฯˆ = ... (usual MHD terms)
โˆ‚ฯˆ/โˆ‚t + c_hยฒ โˆ‡ยทB = -c_hยฒ ฯˆ / ฯ„

์—ฌ๊ธฐ์„œ $c_h$๋Š” ์ฒญ์†Œ ์†๋„(์ผ๋ฐ˜์ ์œผ๋กœ $c_h \sim c_{fast}$)์ด๊ณ  $\tau$๋Š” ๊ฐ์‡  ์‹œ๊ฐ„ ์ฒ™๋„์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋ฐœ์‚ฐ ์˜ค์ฐจ๋ฅผ ํŒŒ๋™์œผ๋กœ ์˜์—ญ ๋ฐ–์œผ๋กœ ์ „ํŒŒํ•ฉ๋‹ˆ๋‹ค.

์žฅ์ : ๋น„๊ตฌ์กฐํ™” ๊ทธ๋ฆฌ๋“œ์—์„œ ์ž‘๋™, CT๋ณด๋‹ค ๊ตฌํ˜„ ์‰ฌ์›€ ๋‹จ์ : $\nabla \cdot B = 0$์„ ์ •ํ™•ํžˆ ๋ณด์žฅํ•˜์ง€ ์•Š์Œ, ๋งค๊ฐœ๋ณ€์ˆ˜ ํŠœ๋‹ ํ•„์š”

9.3 ์–‘์„ฑ์„ฑ ๋ณด์กด ๋ฐฉ๋ฒ•(Positivity-Preserving Methods)

๊ฐ ์—…๋ฐ์ดํŠธ ํ›„ $\rho > 0$๊ณผ $p > 0$์„ ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ •์„ฑ์— ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ฒ•: - ์žฌ๊ตฌ์„ฑ๋œ ์ƒํƒœ๋ฅผ ๋ฌผ๋ฆฌ์  ๋ฒ”์œ„๋กœ ์ œํ•œ - ์Œ์˜ ๋ฐ€๋„/์••๋ ฅ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ”Œ๋Ÿญ์Šค ์กฐ์ • - ์–‘์„ฑ์„ฑ ๋ณด์กด Riemann ์†”๋ฒ„

9.4 ๊ณ ์ฐจ ๋ฐฉ๋ฒ•

2์ฐจ๋ฅผ ๋„˜์–ด: - WENO5: 5์ฐจ ์žฌ๊ตฌ์„ฑ - Discontinuous Galerkin (DG): ์…€ ๋‚ด ๊ณ ์ฐจ, ํ”Œ๋Ÿญ์Šค๋ฅผ ํ†ตํ•ด ๊ฒฐํ•ฉ - ์ŠคํŽ™ํŠธ๋Ÿด ๋ฐฉ๋ฒ•: ๋งค๋„๋Ÿฌ์šด ๋ฌธ์ œ์— ๋Œ€ํ•ด (์ถฉ๊ฒฉํŒŒ์— ์ด์ƒ์ ์ด์ง€ ์•Š์Œ)

์ ˆ์ถฉ: ๊ณ ์ฐจ๋Š” ์ˆ˜์น˜ ์†Œ์‚ฐ์„ ์ค„์ด์ง€๋งŒ ๋น„์šฉ๊ณผ ๋ณต์žก์„ฑ์„ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.

10. ์š”์•ฝ

์ด ๋ ˆ์Šจ์€ 2D MHD๋ฅผ ์œ„ํ•œ ๊ณ ๊ธ‰ ์ˆ˜์น˜ ๊ธฐ๋ฒ•์„ ๋‹ค๋ฃจ์—ˆ์Šต๋‹ˆ๋‹ค:

  1. 2D MHD ๋ฐฉ์ •์‹: 1D๋กœ๋ถ€ํ„ฐ ํ™•์žฅ, 2D์—์„œ 8๊ฐœ์˜ ๋ณด์กด ๋ณ€์ˆ˜
  2. ์œ ํ•œ ์ฒด์ ๋ฒ•: ์…€ ์ค‘์‹ฌ ์ด์‚ฐํ™”, ๋ฐ˜์ด์‚ฐ ํ˜•์‹
  3. ์ฐจ์› ๋ถ„ํ• : Strang splitting (2์ฐจ), 1D ์†”๋ฒ„ ์žฌ์‚ฌ์šฉ
  4. ๋น„๋ถ„ํ•  ๋ฐฉ๋ฒ•: ๋‹ค์ฐจ์› ๊ฒฐํ•ฉ์„ ์œ„ํ•œ CTU
  5. Constrained Transport: ์—‡๊ฐˆ๋ฆฐ ๊ทธ๋ฆฌ๋“œ (Yee mesh), $\nabla \cdot B = 0$ ์ •ํ™•ํžˆ ๋ณด์กด
  6. ๊ณ ์ฐจ ์žฌ๊ตฌ์„ฑ: PLM (์ œํ•œ์ž), WENO (5์ฐจ)
  7. Orszag-Tang ์™€๋ฅ˜: ๋ฒค์น˜๋งˆํฌ ๋ฌธ์ œ, ๋‚œ๋ฅ˜ MHD
  8. Kelvin-Helmholtz ๋ถˆ์•ˆ์ •์„ฑ: ์ž๊ธฐ์žฅ์ด ์ „๋‹จ์ธต ์•ˆ์ •ํ™”
  9. Python ๊ตฌํ˜„: CT๋ฅผ ์‚ฌ์šฉํ•œ 2D MHD๋ฅผ ์œ„ํ•œ ๊ณจ๊ฒฉ ์ฝ”๋“œ

์ƒ์‚ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์œ„ํ•ด์„œ๋Š” ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ํ…Œ์ŠคํŠธ๋˜๊ณ  ์ตœ์ ํ™”๋œ ํ™•๋ฆฝ๋œ ์ฝ”๋“œ(Athena, PLUTO, FLASH)๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

์—ฐ์Šต ๋ฌธ์ œ

  1. CFL ์กฐ๊ฑด: $\Delta x = \Delta y = 0.01$, ๊ณ ์† ์ž๊ธฐ์ŒํŒŒ ์†๋„ $c_f = 2$, ์ตœ๋Œ€ ์œ ๋™ ์†๋„ $|v| = 1$์ธ 2D MHD ์‹œ๋ฎฌ๋ ˆ์ด์…˜์— ๋Œ€ํ•ด $CFL = 0.5$์— ๋Œ€ํ•œ ์ตœ๋Œ€ ํƒ€์ž„์Šคํ…์„ ๊ณ„์‚ฐํ•˜์„ธ์š”.

  2. ๋ฐœ์‚ฐ ๋ณด์กด: ์™œ $B$๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€ ์œ ํ•œ ์ฒด์ ๋ฒ•์€ $\nabla \cdot B = 0$์„ ๋ณด์กดํ•˜์ง€ ์•Š์ง€๋งŒ Constrained Transport๋Š” ๋ณด์กดํ•˜๋Š”์ง€ ์„ค๋ช…ํ•˜์„ธ์š”. Yee mesh๋ฅผ ์Šค์ผ€์น˜ํ•˜๊ณ  $B_x$, $B_y$, $E_z$๊ฐ€ ์–ด๋””์— ์œ„์น˜ํ•˜๋Š”์ง€ ํ‘œ์‹œํ•˜์„ธ์š”.

  3. Orszag-Tang ์™€๋ฅ˜: ์™œ Orszag-Tang ์™€๋ฅ˜๊ฐ€ 2D MHD ์ฝ”๋“œ์— ๋Œ€ํ•œ ์ข‹์€ ํ…Œ์ŠคํŠธ ๋ฌธ์ œ์ž…๋‹ˆ๊นŒ? ์–ด๋–ค ๋ฌผ๋ฆฌ์  ๊ณผ์ •์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๊นŒ (์ตœ์†Œ 3๊ฐœ ๋‚˜์—ด)?

  4. Kelvin-Helmholtz ์•ˆ์ •ํ™”: $V_0 = 2$ m/s, $\rho = 1$ kg/mยณ์ธ ์ „๋‹จ์ธต์— ๋Œ€ํ•ด, KH ๋ถˆ์•ˆ์ •์„ฑ์„ ์–ต์ œํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์ตœ์†Œ ์ž๊ธฐ์žฅ $B_0$์„ ๊ณ„์‚ฐํ•˜์„ธ์š” (์ฆ‰, $v_A \geq V_0$). Tesla๋กœ ํ‘œํ˜„ํ•˜์„ธ์š” (์ง„๊ณต ํˆฌ์ž์œจ $\mu_0 = 4\pi \times 10^{-7}$ H/m ๊ฐ€์ •).

  5. PLM ์žฌ๊ตฌ์„ฑ: ์…€ ์ค‘์‹ฌ ๊ฐ’ $U_{i-1} = 1.0$, $U_i = 1.5$, $U_{i+1} = 2.5$๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ, (a) ์ค‘์‹ฌ ์ฐจ๋ถ„, (b) minmod ์ œํ•œ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ์šธ๊ธฐ $\sigma_i$๋ฅผ ๊ณ„์‚ฐํ•˜์„ธ์š”. ์…€ ๊ฒฝ๊ณ„๋ฉด $i+1/2$์—์„œ ์ขŒ์ธก๊ณผ ์šฐ์ธก ์ƒํƒœ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

  6. CT ์ „๊ธฐ์žฅ: Constrained Transport์—์„œ ์…€ ์ฝ”๋„ˆ์˜ ์ „๊ธฐ์žฅ $E_z$๋Š” ์ธ์ ‘ํ•œ ๋ฉด์˜ ์†๋„์™€ ์ž๊ธฐ์žฅ์œผ๋กœ๋ถ€ํ„ฐ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค. 4๊ฐœ์˜ ์ฃผ๋ณ€ ๋ฉด ์ค‘์‹ฌ์—์„œ $v_x$, $v_y$, $B_x$, $B_y$์— ๋Œ€ํ•ด $E_z(i, j)$์˜ ๊ณต์‹์„ ์ž‘์„ฑํ•˜์„ธ์š”. (๊ฐ„๋‹จํ•œ ํ‰๊ท ํ™” ๊ฐ€์ •.)

  7. ์ฐจ์› ๋ถ„ํ•  ์˜ค์ฐจ: Strang splitting ($L_x^{1/2} L_y L_x^{1/2}$)์€ ์‹œ๊ฐ„์— ๋Œ€ํ•ด 2์ฐจ ์ •ํ™•๋„์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ splitting ($L_x L_y$)์„ ์‚ฌ์šฉํ•˜๋ฉด ์ •ํ™•๋„์˜ ์ฐจ์ˆ˜๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์™œ Strang splitting์ด ์„ ํ˜ธ๋ฉ๋‹ˆ๊นŒ?

  8. WENO ์žฅ์ : WENO ๊ธฐ๋ฒ•์€ ๋งค๋„๋Ÿฌ์šด ์˜์—ญ์—์„œ 5์ฐจ ์ •ํ™•ํ•˜์ง€๋งŒ ๋ถˆ์—ฐ์† ๊ทผ์ฒ˜์—์„œ ๋” ๋‚ฎ์€ ์ฐจ์ˆ˜๋กœ ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค. ์™œ ์ด๊ฒƒ์ด ํ•ญ์ƒ 2์ฐจ PLM์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๋น„ํ•ด ์œ ์ตํ•ฉ๋‹ˆ๊นŒ?

  9. AMR ์ •์ œ ๊ธฐ์ค€: MHD ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ ์ „๋ฅ˜ ์‹œํŠธ ๊ทผ์ฒ˜์—์„œ ๊ทธ๋ฆฌ๋“œ๋ฅผ ์ •์ œํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. $|\nabla \times B|$์— ๊ธฐ๋ฐ˜ํ•œ ์ •์ œ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ์ค€์„ ์ œ์•ˆํ•˜์„ธ์š”. ์กฐ๊ฑด์„ ์ˆ˜ํ•™์ ์œผ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”.

  10. ๊ณ„์‚ฐ ๋น„์šฉ: ๋™์ผํ•œ ๋ฌผ๋ฆฌ์™€ Riemann ์†”๋ฒ„๋ฅผ ๊ฐ€์ •ํ•˜์—ฌ $256 \times 256$ ๊ทธ๋ฆฌ๋“œ์—์„œ์˜ 2D MHD ์‹œ๋ฎฌ๋ ˆ์ด์…˜๊ณผ 256 ์…€์ด ์žˆ๋Š” 1D ์‹œ๋ฎฌ๋ ˆ์ด์…˜์˜ ๊ณ„์‚ฐ ๋น„์šฉ(ํƒ€์ž„์Šคํ…๋‹น ์—ฐ์‚ฐ)์„ ๋น„๊ตํ•˜์„ธ์š”. ๋น„์œจ์„ ์ถ”์ •ํ•˜์„ธ์š” (์ƒ์ˆ˜ ๋ฌด์‹œ).


์ด์ „: ์šฐ์ฃผ ๊ธฐ์ƒ MHD | ๋‹ค์Œ: ์ƒ๋Œ€๋ก ์  MHD

to navigate between lessons