Temperatur Virtual dan Densitas Udara
Ada pertanyaan yang terlihat sederhana namun sering terlewat: apakah udara lembap lebih berat atau lebih ringan dari udara kering? Jawabannya berlawanan dengan intuisi — udara lembap justru lebih ringan. Penyebabnya ada di level molekuler: uap air (H₂O) memiliki massa molar 18 g/mol, jauh lebih ringan dari rata-rata campuran nitrogen dan oksigen di udara kering yang mendekati 29 g/mol. Ketika uap air menggantikan sebagian molekul-molekul berat itu, densitas keseluruhan udara berkurang.
Masalahnya, persamaan gas ideal standar untuk udara kering:
$$p = \rho R_d T$$
menggunakan konstanta gas udara kering \(R_d = 287{,}05\ \mathrm{J\,kg^{-1}\,K^{-1}}\) — sebuah nilai tetap. Begitu udara mengandung uap air, gas constant efektifnya berubah bergantung kandungan kelembapan. Menghitung densitas secara langsung dari \(T\) saja mengabaikan efek itu dan menghasilkan nilai yang tidak tepat.
Solusi elegan yang dipakai meteorologi operasional adalah virtual temperature (\(T_v\)): suhu yang harus dimiliki udara kering agar densitasnya sama dengan udara lembap pada tekanan yang sama. Dengan \(T_v\), persamaan gas ideal tetap menggunakan \(R_d\):
$$\rho = \frac{p}{R_d T_v}$$
Ini bukan sekadar formalitas matematis. Mengabaikan koreksi virtual temperature dapat menghasilkan error yang signifikan pada perhitungan buoyancy, CAPE, dan boundary layer height — terutama di lingkungan tropis yang lembap seperti Indonesia. Tutorial ini menghitung \(T_v\) dan densitas udara langsung dari data ERA5 di 850 hPa dan 500 hPa, membandingkan hasilnya, lalu memvisualisasikan distribusi spasialnya di atas kepulauan.
Menyiapkan Data ERA5 pada Level Tekanan
Kita butuh dua variabel dari ERA5: temperature (\(T\) dalam Kelvin) dan specific humidity (\(q\) dalam kg/kg) pada pressure level 500 dan 850 hPa untuk seluruh tahun 2024 di bounding box Indonesia. Download dilakukan satu kali lewat cdsapi — selanjutnya snippet berikutnya membaca file lokal yang sama tanpa perlu koneksi ke CDS lagi.
Untuk mendaftar akun CDS dan mengaktifkan API key, kunjungi cds.climate.copernicus.eu.
Snippet di bawah mendefinisikan fungsi fetch_era5() yang memeriksa keberadaan file lebih dulu; jika file sudah ada di direktori kerja, proses download dilewati sehingga kita tidak perlu menunggu antrian CDS ulang.
import os
import cdsapi
import xarray as xr
BBOX = [6, 95, -11, 141] # N, W, S, E — Indonesia
MONTHS = [f"{m:02d}" for m in range(1, 13)]
DAYS = [f"{d:02d}" for d in range(1, 32)]
def fetch_era5(out, variable):
if not os.path.exists(out):
c = cdsapi.Client(quiet=True)
c.retrieve(
"reanalysis-era5-pressure-levels",
{
"product_type": "reanalysis",
"variable": [variable],
"pressure_level": ["500", "850"],
"year": "2024",
"month": MONTHS,
"day": DAYS,
"time": "00:00",
"area": BBOX,
"format": "netcdf",
},
out,
)
fetch_era5("era5_t_pl500-850_indonesia_2024_d.nc", "temperature")
fetch_era5("era5_q_pl500-850_indonesia_2024_d.nc", "specific_humidity")
ds_t = xr.open_dataset("era5_t_pl500-850_indonesia_2024_d.nc")
ds_q = xr.open_dataset("era5_q_pl500-850_indonesia_2024_d.nc")
print(ds_t)
print("\nVariabel q:", list(ds_q.data_vars), "| pressure_level:", ds_q["pressure_level"].values)
<xarray.Dataset> Size: 37MB
Dimensions: (valid_time: 366, pressure_level: 2, latitude: 69,
longitude: 185)
Coordinates:
* valid_time (valid_time) datetime64[ns] 3kB 2024-01-01 ... 2024-12-31
expver (valid_time) <U4 6kB ...
* pressure_level (pressure_level) float64 16B 850.0 500.0
* latitude (latitude) float64 552B 6.0 5.75 5.5 ... -10.5 -10.75 -11.0
* longitude (longitude) float64 1kB 95.0 95.25 95.5 ... 140.8 141.0
number int64 8B ...
Data variables:
t (valid_time, pressure_level, latitude, longitude) float32 37MB ...
Attributes:
GRIB_centre: ecmf
GRIB_centreDescription: European Centre for Medium-Range Weather Forecasts
GRIB_subCentre: 0
Conventions: CF-1.7
institution: European Centre for Medium-Range Weather Forecasts
history: 2026-05-10T04:10 GRIB to CDM+CF via cfgrib-0.9.1...
Variabel q: ['q'] | pressure_level: [850. 500.]
Output di atas menampilkan dimensi dataset: valid_time (366 hari sepanjang 2024 yang merupakan tahun kabisat, satu timestep 00Z per hari), pressure_level (2 level: 500 dan 850 hPa), latitude, dan longitude. Variabel t tersedia dalam Kelvin; q dalam kg/kg — keduanya siap dipakai langsung di snippet berikutnya.
Menghitung Temperatur Virtual
Formula \(T_v\) diturunkan dari hukum gas parsial Dalton untuk campuran udara kering dan uap air. Bentuk eksaknya:
$$T_v = T \frac{1 + w/\varepsilon}{1 + w}$$
di mana \(w\) adalah water-vapor mixing ratio (kg/kg) dan \(\varepsilon = R_d/R_v \approx 0{,}622\), dengan \(R_v = 461\ \mathrm{J\,kg^{-1}\,K^{-1}}\). Konstanta yang muncul dalam aproksimasi linear adalah \(0{,}608 = (1 - \varepsilon)/\varepsilon\). Untuk rentang tropik tipikal \(w \approx 0{,}001\)–\(0{,}025\) kg/kg, penyebut \((1 + w)\) mendekati 1 dan formula menyederhanakan menjadi:
$$T_v \approx T\,(1 + 0{,}608\, q)$$
ERA5 menyediakan specific humidity \(q\) secara langsung pada setiap pressure level. Nilainya hampir identik dengan \(w\) pada kelembapan atmosferik normal (perbedaannya menghasilkan error \(< 0{,}05\) K di 850 hPa dan dapat diabaikan di 500 hPa), sehingga kita bisa menggunakan \(q\) dari ERA5 tanpa konversi tambahan.
Karena \(q > 0\) selalu untuk udara tidak jenuh, \(T_v > T\) selalu berlaku. Besarnya koreksi bergantung pada kandungan uap air: di 850 hPa di atas Indonesia yang lembap, koreksi rata-ratanya sekitar 2 K; di 500 hPa, udara jauh lebih kering sehingga koreksinya turun ke sekitar 0,6 K — beberapa kali lebih kecil.
import numpy as np
T = ds_t["t"] # Kelvin, dims (valid_time, pressure_level, latitude, longitude)
q = ds_q["q"] # specific humidity, kg/kg
# Temperatur virtual: Tv = T (1 + 0.608 q)
Tv = T * (1 + 0.608 * q)
for lev in [850, 500]:
T_lev = T.sel(pressure_level=lev)
Tv_lev = Tv.sel(pressure_level=lev)
dT = Tv_lev - T_lev
print(f"--- {lev} hPa ---")
print(f" T rata-rata : {float(T_lev.mean()):.2f} K")
print(f" Tv rata-rata : {float(Tv_lev.mean()):.2f} K")
print(f" Tv - T (mean) : {float(dT.mean()):.3f} K")
print(f" Tv - T (maks) : {float(dT.max()):.3f} K")
--- 850 hPa ---
T rata-rata : 291.52 K
Tv rata-rata : 293.64 K
Tv - T (mean) : 2.128 K
Tv - T (maks) : 3.363 K
--- 500 hPa ---
T rata-rata : 268.91 K
Tv rata-rata : 269.48 K
Tv - T (mean) : 0.572 K
Tv - T (maks) : 1.298 K
Output di atas akan memperlihatkan bahwa \(T_v - T\) rata-rata di 850 hPa secara konsisten jauh lebih besar dari 500 hPa — mengkonfirmasi bahwa profil specific humidity turun tajam seiring bertambahnya ketinggian di atmosfer tropis.
Densitas Udara dari Persamaan Gas Ideal
Dengan \(T_v\) tersedia, menghitung densitas udara tinggal menyusun ulang persamaan gas ideal:
$$\rho = \frac{p}{R_d T_v}$$
Tekanan harus dikonversi dari hPa ke Pascal (kalikan 100). Seluruh efek kelembapan sudah terserap dalam \(T_v\), sehingga \(R_d = 287{,}05\ \mathrm{J\,kg^{-1}\,K^{-1}}\) tetap dipakai — tidak perlu gas constant moist air yang berubah-ubah setiap saat. Ini persis keunggulan virtual temperature: satu substitusi sederhana, dan seluruh framework udara kering tetap valid.
Untuk memperlihatkan pentingnya koreksi secara kuantitatif, snippet di bawah menghitung densitas dua kali: sekali memakai \(T_v\) (benar) dan sekali memakai \(T\) biasa yang mengabaikan uap air, kemudian melaporkan selisihnya dalam kg/m³ sekaligus persentase error:
Rd = 287.05 # J/(kg·K) — konstanta gas udara kering
for lev in [850, 500]:
p = lev * 100.0 # hPa -> Pa
Tv_lev = Tv.sel(pressure_level=lev)
T_lev = T.sel(pressure_level=lev)
rho_moist = p / (Rd * Tv_lev) # densitas benar (pakai Tv)
rho_dry = p / (Rd * T_lev) # keliru: mengabaikan uap air
d_rho = rho_dry - rho_moist
print(f"--- {lev} hPa (p = {p:.0f} Pa) ---")
print(f" rho pakai Tv : {float(rho_moist.mean()):.4f} kg/m3")
print(f" rho pakai T : {float(rho_dry.mean()):.4f} kg/m3")
print(f" selisih : {float(d_rho.mean()):.4f} kg/m3 "
f"({100*float((d_rho/rho_moist).mean()):.2f} %)")
--- 850 hPa (p = 85000 Pa) ---
rho pakai Tv : 1.0084 kg/m3
rho pakai T : 1.0158 kg/m3
selisih : 0.0074 kg/m3 (0.73 %)
--- 500 hPa (p = 50000 Pa) ---
rho pakai Tv : 0.6464 kg/m3
rho pakai T : 0.6478 kg/m3
selisih : 0.0014 kg/m3 (0.21 %)
Perbedaan densitas di 850 hPa terlihat kecil dalam nilai absolut, tetapi persentase errornya cukup bermakna untuk perhitungan buoyancy — karena buoyancy bergantung pada selisih densitas antara parcel dan lingkungannya, dan selisih itu sendiri kecil. Mengabaikan virtual temperature berarti secara sistematis melebih-estimasi densitas udara lembap, yang pada akhirnya meremehkan buoyancy dan CAPE. Di 500 hPa, selisihnya jauh lebih kecil karena udara memang jauh lebih kering di atmosfer tengah.
Memvisualisasikan Koreksi Virtual di 850 hPa
Peta berikut menampilkan rata-rata tahunan \(T_v - T\) di 850 hPa di atas Indonesia untuk tahun 2024. Rentang warna yang lebih gelap (oranye-merah) menunjukkan wilayah dengan koreksi virtual temperature lebih besar — umumnya di atas laut yang hangat dan lembap di mana massa udara moist persisten sepanjang tahun.
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
dTv = (Tv - T).sel(pressure_level=850).mean("valid_time")
lon = dTv["longitude"].values
lat = dTv["latitude"].values
fig = plt.figure(figsize=(11, 6))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_extent([95, 141, -11, 6], crs=ccrs.PlateCarree())
mesh = ax.pcolormesh(lon, lat, dTv.values, transform=ccrs.PlateCarree(),
cmap="YlOrRd", shading="auto")
ax.add_feature(cfeature.COASTLINE.with_scale("50m"), linewidth=0.6)
ax.add_feature(cfeature.BORDERS.with_scale("50m"), linewidth=0.3, linestyle=":")
gl = ax.gridlines(draw_labels=True, linewidth=0.3, color="gray", alpha=0.5)
gl.top_labels = False
gl.right_labels = False
plt.colorbar(mesh, ax=ax, orientation="horizontal", pad=0.07, shrink=0.8,
label="Tv - T (K)")
ax.set_title("Koreksi Temperatur Virtual Rata-rata 2024 di 850 hPa",
fontsize=12, weight="bold", pad=10)
plt.savefig("tv_correction_850.png", dpi=150, bbox_inches="tight")
print("rentang Tv-T:", f"{float(dTv.min()):.2f} .. {float(dTv.max()):.2f} K")
Gradasi warna pada peta mengungkap pola spasial yang jelas: Samudra Pasifik bagian barat, Laut Jawa, dan wilayah laut di sekitar Sumatera bagian barat memiliki koreksi lebih besar dibanding dataran tinggi Papua dan pegunungan Sulawesi interior — mencerminkan dominasi uap air di atas permukaan laut yang hangat sepanjang tahun dibandingkan daratan yang relatif lebih kering.
Penutup dan Langkah Berikutnya
Virtual temperature adalah konsep yang sederhana dalam rumusnya — \(T_v = T(1 + 0{,}608\,q)\) — tetapi penting dalam praktiknya. Ia memungkinkan seluruh termodinamika udara lembap ditangani lewat satu substitusi di persamaan gas ideal, tanpa mengubah \(R_d\) di setiap turunan berikutnya. Hasilnya, densitas udara selalu bisa dihitung sebagai \(\rho = p/(R_d T_v)\), konsisten untuk udara kering maupun lembap.
Dari tutorial ini kita sudah melihat bahwa koreksi di 850 hPa secara rata-rata beberapa kali lebih besar dari 500 hPa — konsekuensi langsung dari profil specific humidity yang turun tajam seiring ketinggian di atmosfer tropis. Dalam konteks operasional, \(T_v\) menjadi input langsung pada perhitungan CAPE, parcel buoyancy, dan diagnosis pra-konvektif untuk cuaca ekstrem.
Langkah berikutnya yang natural: gunakan \(T_v\) dari artikel ini sebagai titik masuk untuk menghitung CAPE atau lifted index dari sounding ERA5 di berbagai lokasi di Indonesia. Kita juga bisa memperluas analisis ke 925 hPa untuk melihat koreksi yang bahkan lebih besar di dekat permukaan, atau membandingkan \(T_v - T\) antar musim untuk memetakan pengaruh monsun terhadap kandungan uap air di seluruh kepulauan.
Eksplorasi artikel meteorologi lainnya di meteo.my.id — buka di sini.
Referensi
- Virtual Temperature — QuickStudies for Graduate Students (David Randall, CSU) — Derivasi virtual temperature dari prinsip pertama; sumber utama untuk formula eksak dan konstanta 0,608.
- NOAA National Weather Service Glossary — Virtual Temperature — Definisi operasional resmi yang digunakan forecaster NOAA/NWS.
- ESS 55 — Atmospheric Thermodynamics Lecture Notes (UC Irvine) — Penjelasan gas constant udara kering vs lembap dan motivasi fisika penggunaan virtual temperature; sumber nilai Rd dan Rv.
- Virtual temperature — Wikipedia — Tinjauan formula, konstanta, dan aplikasi termasuk CAPE dan buoyancy; merangkum definisi AMS dan WMO sebagai referensi sekunder.
Tidak ada komentar:
Posting Komentar