Senin, 27 Juli 2026
Latar Belakang Frontogenesis
Sumber: NASA Earth Observatory (link) — "A Textbook Weather Front", citra GOES-16 (12 September 2019).
Ketika dua massa udara dengan karakteristik termal berbeda bertemu dan gradien suhu horizontalnya menguat secara tajam, kita menyebutnya frontogenesis. Di lintang menengah, proses ini mudah terlihat di citra satelit: front dingin membawa deretan konveksi kuat dan anvil-shaped clouds, sementara front hangat menghasilkan lapisan awan stratiform luas dengan presipitasi yang lebih merata. Perbedaan visual ini bukan kebetulan — intensitas, lebar, dan orientasi pita awan berkorelasi langsung dengan besarnya nilai frontogenesis di atmosfer bawah.
Secara formal, frontogenesis adalah laju perubahan magnitudo gradien horizontal suhu potensial \(\theta\) mengikuti gerak fluida:
$$F = \frac{D}{Dt}|\nabla_H \theta|$$
Nilai \(F > 0\) berarti gradien menguat (frontogenesis); \(F < 0\) berarti melemah (frontolisis).
Di Maritime Continent dan wilayah Indonesia, front sinoptik klasik nyaris tidak ada — gaya Coriolis mendekati nol di dekat ekuator sehingga keseimbangan geostrofik yang menopang front tidak terbentuk. Namun cold surge dari Siberia dan Asia Timur selama DJF (Desember–Februari) dapat mendorong batas massa udara dingin ke Laut Cina Selatan dan perairan sekitar Kalimantan, memunculkan gradien \(\theta\) yang terdeteksi di 850 hPa. Zona konvergensi seperti ITCZ dan batas monsun juga menghasilkan nilai frontogenesis yang berguna secara diagnostik meski bukan front klasik.
Sirkulasi sekunder ageostrofik yang dipicu frontogenesis — gerak naik di sisi hangat, turun di sisi dingin — bertanggung jawab langsung atas pita awan dan presipitasi terkonsentrasi. Tutorial ini menghitung fungsi frontogenesis Petterssen 2D dari ERA5 850 hPa untuk Indonesia, lalu memvisualisasikannya sebagai peta menggunakan Python, NumPy, dan Matplotlib.
Data dan Setup ERA5
ERA5 dari ECMWF menyediakan reanalysis global dengan resolusi horizontal ~31 km (0,25°) dan temporal hingga satu jam — resolusi tertinggi di antara reanalysis global yang tersedia secara bebas. Untuk frontogenesis troposfer bawah, 850 hPa adalah level standar: cukup tinggi untuk menghindari terrain noise, cukup rendah untuk menangkap batas massa udara dekat permukaan.
Kita membutuhkan tiga variabel pressure-level: temperature (\(T\)), komponen angin zonal (\(u\)), dan meridional (\(v\)). Semua tersedia di CDS (Copernicus Data Store). Untuk mendaftar akun dan mengonfigurasi ~/.cdsapirc dengan API key, kunjungi cds.climate.copernicus.eu. Snippet di bawah mengunduh tiga file NetCDF untuk bbox Indonesia (95°E–141°E, -11°S–6°N) tahun 2024. Guard os.path.exists memastikan pengunduhan hanya terjadi sekali — jalankan ulang snippet dan CDS tidak akan diakses lagi.
import os, cdsapi, xarray as xr
# Unduh sekali dari CDS; menjalankan ulang tidak mengunduh lagi berkat guard os.path.exists.
FILES = {
"temperature": "era5_t_pl500-850_indonesia_2024_d.nc",
"u_component_of_wind": "era5_u_pl500-850_indonesia_2024_d.nc",
"v_component_of_wind": "era5_v_pl500-850_indonesia_2024_d.nc",
}
for var, out in FILES.items():
if not os.path.exists(out):
c = cdsapi.Client(quiet=True)
c.retrieve("reanalysis-era5-pressure-levels", {
"product_type": "reanalysis",
"variable": [var],
"pressure_level": ["500", "850"],
"year": "2024",
"month": [f"{m:02d}" for m in range(1, 13)],
"day": [f"{d:02d}" for d in range(1, 32)],
"time": "00:00",
"area": [6, 95, -11, 141],
"format": "netcdf",
}, out)
t = xr.open_dataset(FILES["temperature"])["t"].sel(pressure_level=850)
u = xr.open_dataset(FILES["u_component_of_wind"])["u"].sel(pressure_level=850)
v = xr.open_dataset(FILES["v_component_of_wind"])["v"].sel(pressure_level=850)
print("Dimensi t @850 hPa:", dict(t.sizes))
print("Rentang waktu:", str(t['valid_time'].min().values)[:10],
"s/d", str(t['valid_time'].max().values)[:10])
print("Grid:", t['latitude'].size, "titik lintang x", t['longitude'].size, "titik bujur")
Dimensi t @850 hPa: {'valid_time': 366, 'latitude': 69, 'longitude': 185}
Rentang waktu: 2024-01-01 s/d 2024-12-31
Grid: 69 titik lintang x 185 titik bujur
Output di atas mengonfirmasi dimensi dataset dan rentang waktu yang tercakup. Variabel t, u, dan v sudah diseleksi ke 850 hPa dan siap digunakan di snippet berikutnya sebagai shared globals.
Menghitung Suhu Potensial pada 850 hPa
Mengapa kita menggunakan \(\theta\) dan bukan \(T\) biasa? Suhu potensial adalah temperatur yang akan dimiliki parsel udara kering jika dibawa secara adiabatik ke tekanan referensi \(p_0 = 1000\) hPa:
$$\theta = T\left(\frac{p_0}{p}\right)^{R/c_p}$$
dengan \(R/c_p \approx 0{,}286\) (konstanta Poisson udara kering). Karena \(\theta\) lestari dalam proses adiabatik kering, perubahan \(|\nabla\theta|\) yang mengikuti gerak fluida hanya mencerminkan efek kinematik angin pada medan termal — bukan kompresi atau ekspansi adiabatik akibat gerak vertikal. Itulah alasan fungsi frontogenesis Petterssen menggunakan \(\theta\) sebagai tracer, bukan \(T\).
Setelah menghitung \(\theta\), kita hitung magnitudo gradien horizontalnya:
$$|\nabla\theta| = \sqrt{(\partial\theta/\partial x)^2 + (\partial\theta/\partial y)^2}$$
Sumber: NASA Earth Observatory (link) — struktur front dari radar CloudSat.
Diferensial numerik menggunakan np.gradient dengan interval grid dikonversi ke meter. Koreksi penyempitan meridian — faktor \(\cos\phi\) pada komponen bujur — penting untuk akurasi: pada lintang 6°N, selisih 0,25° bujur setara ~27 km, sedangkan di lintang -11°S nilainya sedikit lebih besar. Kita ambil snapshot 15 Januari 2024 sebagai tanggal representatif DJF, periode cold surge paling aktif di Asia Tenggara.
import numpy as np
DATE = "2024-01-15" # musim DJF, saat cold surge aktif di Asia Tenggara
t850 = t.sel(valid_time=DATE).squeeze()
u850 = u.sel(valid_time=DATE).squeeze()
v850 = v.sel(valid_time=DATE).squeeze()
lat = t850["latitude"].values
lon = t850["longitude"].values
R_EARTH = 6.371e6
# Suhu potensial di 850 hPa: theta = T (1000/p)^(R/cp), R/cp = 0.286
theta = t850.values * (1000.0 / 850.0) ** 0.286
lat_rad, lon_rad = np.deg2rad(lat), np.deg2rad(lon)
coslat = np.cos(lat_rad)[:, None]
def ddx(f): # turunan terhadap x (meter), memperhitungkan penyempitan meridian
return np.gradient(f, lon_rad, axis=1) / (R_EARTH * coslat)
def ddy(f): # turunan terhadap y (meter); np.gradient menangani lintang menurun
return np.gradient(f, lat_rad, axis=0) / R_EARTH
dtheta_dx, dtheta_dy = ddx(theta), ddy(theta)
grad_mag = np.sqrt(dtheta_dx**2 + dtheta_dy**2) # K/m
print(f"theta 850 hPa: min={theta.min():.1f} K, rata2={theta.mean():.1f} K, maks={theta.max():.1f} K")
print(f"|grad theta| rata-rata: {grad_mag.mean()*1e5:.3f} K per 100 km")
theta 850 hPa: min=303.2 K, rata2=305.5 K, maks=308.7 K
|grad theta| rata-rata: 0.630 K per 100 km
Output di atas menunjukkan rentang nilai \(\theta\) tipikal troposfer bawah Indonesia serta magnitudo rata-rata gradien suhu potensial dalam K per 100 km — angka ini menjadi pembilang utama dalam fungsi frontogenesis.
Deformasi Angin dan Divergensi
Frontogenesis tidak hanya bergantung pada seberapa besar \(|\nabla\theta|\) saat ini, melainkan pada seberapa cepat angin memodifikasinya. Dua proses kinematik utama berperan: deformasi dan divergensi.
Deformasi total \(E\) merupakan gabungan dua komponen. Deformasi stretching, \(E_{st} = \partial u/\partial x - \partial v/\partial y\), meregangkan isoterm sepanjang sumbu dilatasi — angin yang bergerak berlawanan arah pada lintang yang sama "memeras" isoterm dari dua sisi sehingga isoterm merapatkan diri. Deformasi shearing, \(E_{sh} = \partial v/\partial x + \partial u/\partial y\), memutar dan menggeser isoterm secara lateral. Keduanya digabung secara kuadratur:
$$E = \sqrt{E_{st}^2 + E_{sh}^2}$$
Divergensi horizontal \(\delta = \partial u/\partial x + \partial v/\partial y\) bersifat frontolitis secara langsung — konvergensi (\(\delta < 0\)) cenderung mengencangkan gradien, sedangkan divergensi (\(\delta > 0\)) meregangkan dan melemahkannya.
Efisiensi deformasi dalam mengencangkan gradien bergantung pada sudut \(\beta\) antara sumbu dilatasi dan isoterm-\(\theta\). Ketika \(\beta \approx 0°\) (sumbu dilatasi sejajar isoterm), \(\cos(2\beta) \approx 1\) dan deformasi paling efisien secara frontogenetik. Pada \(\beta = 45°\), kontribusi bersihnya nol. Pada \(\beta = 90°\) (sumbu dilatasi tegak lurus isoterm), deformasi justru melemahkan gradien — bersifat frontolitis. Di snippet berikutnya, kita hitung semua komponen ini sekaligus bersama fungsi frontogenesis penuh.
Fungsi Petterssen Frontogenesis
Bentuk kompak fungsi Petterssen 2D menggabungkan semua kuantitas kinetik dalam satu ekspresi:
$$F = \tfrac{1}{2}|\nabla\theta|\left(E\cos 2\beta - \delta\right)$$
Dalam implementasi numerik, menghitung \(\beta\) secara eksplisit membutuhkan langkah tambahan. Bentuk gradien yang secara aljabar ekuivalen — dan itulah yang digunakan MetPy serta kode di bawah ini — menghindari kalkulasi sudut tersebut dengan mengekspansi langsung ke suku-suku turunan parsial:
$$F = -\frac{(\partial\theta/\partial x)^2\,(\partial u/\partial x) + (\partial\theta/\partial y)^2\,(\partial v/\partial y) + (\partial\theta/\partial x)(\partial\theta/\partial y)(\partial u/\partial y + \partial v/\partial x)}{|\nabla\theta|}$$
Hasilnya dalam satuan K/m/s. Konversi ke satuan konvensional prakiraan sinoptik mengalikan dengan \(1{,}08 \times 10^9\) sehingga output dalam K per 100 km per 3 jam.
# Komponen deformasi dan divergensi dari medan angin 850 hPa
dudx, dudy = ddx(u850.values), ddy(u850.values)
dvdx, dvdy = ddx(v850.values), ddy(v850.values)
stretching = dudx - dvdy # deformasi stretching
shearing = dvdx + dudy # deformasi shearing
total_def = np.sqrt(stretching**2 + shearing**2)
divergence = dudx + dvdy
# Fungsi frontogenesis Petterssen (bentuk gradien)
eps = 1e-12
F = -(dtheta_dx**2 * dudx
+ dtheta_dy**2 * dvdy
+ dtheta_dx * dtheta_dy * (dudy + dvdx)) / (grad_mag + eps) # K/m/s
F_conv = F * 1.08e9 # konversi ke K per 100 km per 3 jam
print(f"deformasi total rata-rata: {total_def.mean():.2e} /s")
print(f"divergensi rata-rata: {divergence.mean():.2e} /s")
print(f"F: min={np.nanmin(F_conv):.2f}, rata2={np.nanmean(F_conv):.2f}, "
f"maks={np.nanmax(F_conv):.2f} (K/100km/3jam)")
print(f"fraksi area frontogenetik (F>0): {np.mean(F_conv>0):.0%}")
deformasi total rata-rata: 3.23e-05 /s
divergensi rata-rata: -1.55e-06 /s
F: min=-2.84, rata2=0.02, maks=1.79 (K/100km/3jam)
fraksi area frontogenetik (F>0): 56%
Output di atas merangkum statistik frontogenesis untuk 15 Januari 2024: nilai deformasi dan divergensi dalam per-detik, rentang \(F\) dalam K/100km/3jam, dan fraksi area yang sedang mengalami frontogenesis. Di lintang tropis, fraksi area frontogenetik sering mendekati 50% — batas massa udara lebih difus dibanding front sinoptik tegas di lintang menengah, namun pola spasialnya tetap bermakna secara diagnostik.
Visualisasi dan Interpretasi Frontogenesis
Dengan semua komponen tersimpan di memori, kita buat peta 2D frontogenesis. Colormap diverging berpusat di nol menonjolkan zona frontogenetik (\(F > 0\), merah) dan frontolitis (\(F < 0\), biru). Kontur \(\theta\) di atas peta membantu membaca orientasi isoterm relatif terhadap struktur angin — apakah deformasi sejajar atau melintang terhadap isoterm.
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(9, 5))
vmax = np.nanpercentile(np.abs(F_conv), 98)
pcm = ax.pcolormesh(lon, lat, F_conv, cmap="RdBu_r",
vmin=-vmax, vmax=vmax, shading="auto")
cs = ax.contour(lon, lat, theta, colors="k", linewidths=0.4, levels=10)
ax.clabel(cs, inline=True, fontsize=6, fmt="%d")
ax.set_xlabel("Bujur (°E)")
ax.set_ylabel("Lintang (°)")
ax.set_title(f"Fungsi Frontogenesis 850 hPa — {DATE}")
cb = fig.colorbar(pcm, ax=ax, shrink=0.85)
cb.set_label("F (K / 100 km / 3 jam)")
fig.savefig("frontogenesis_850hpa.png", dpi=120, bbox_inches="tight")
print("Peta frontogenesis tersimpan.")
Peta di atas menampilkan distribusi spasial frontogenesis 850 hPa pada 15 Januari 2024. Zona merah intens biasanya terkonsentrasi di area konfluensi angin — tepian selatan cold surge, batas ITCZ, atau zona pertemuan angin monsun di sekitar Laut Cina Selatan dan selat-selat antar pulau besar. Nilai \(F\) negatif (biru) muncul di area difluensi tempat angin menyebar.
Sirkulasi sekunder ageostrofik yang dipicu frontogenesis — gerak naik di sisi hangat, turun di sisi dingin — bertanggung jawab langsung atas pita awan dan presipitasi terkonsentrasi yang terlihat di citra satelit sepanjang zona frontal. Pada prakiraan operasional, peta frontogenesis 850 hPa membantu forecaster mengidentifikasi di mana presipitasi frontal kemungkinan paling intens bahkan sebelum radar atau citra inframerah menunjukkan tanda jelas.
Dari sini, eksplorasi bisa dilanjutkan ke beberapa arah: rata-rata bulanan \(F\) dari seluruh data 2024 untuk melihat variabilitas musiman frontogenesis di Indonesia, kombinasi peta frontogenesis dengan medan OLR untuk mengkorelasikan zona frontogenetik dengan konveksi aktif, atau penerapan teknik yang sama ke level 700 hPa untuk perspektif vertikal yang lebih lengkap.
Eksplorasi artikel meteorologi lainnya di meteo.my.id. Kunjungi halaman utama untuk arsip lengkapnya.
Referensi
- frontogenesis — MetPy documentation — Dokumentasi API MetPy untuk fungsi frontogenesis Petterssen, termasuk formula, definisi parameter, dan faktor konversi satuan K/m/s ke K/100km/3h.
- ERA5 data documentation — Copernicus/ECMWF — Dokumentasi teknis ERA5 tentang resolusi grid, level tekanan standar (termasuk 850 hPa), dan variabel yang tersedia untuk analisis frontogenesis.
- Potential Temperature — NOAA NWS Glossary — Definisi suhu potensial, formula Poisson (\(R/c_p \approx 0{,}286\)), dan sifat kelestariannya dalam proses adiabatik kering.
- A Textbook Weather Front — NASA Earth Observatory — Citra GOES-16 + MODIS dari front dingin dan hangat yang "sempurna" di atas Amerika Serikat, 12 September 2019, lengkap dengan penjelasan mekanisme frontal.
- Frontogenetical Function — AMS Glossary of Meteorology — Definisi kanonis fungsi frontogenesis oleh American Meteorological Society, mengikuti Petterssen (1956) dan Bluestein (1993) pp. 248–253.