Commit 8c9e6206 authored by Thomas Dubos's avatar Thomas Dubos
Browse files

Compute correct volumes and masses

Bug is there in computation of DYNAMICO area.
parent 94459644
......@@ -13,11 +13,31 @@ def compute_pressure(ap, bp, p0, ps):
p[i, :, :] = p0*ap[i] + ps*bp[i] # should return a pressure matrix(lat, lon) at each level
return p
def check_compute_pressure(ap, bp, p0, ps, p):
def check_compute_pressure(ap, bp, p0, ps, p, rel_tol=1e-6):
pp = compute_pressure(ap, bp, p0, ps)
dp = np.absolute(pp-p)#.abs()
print("Checking formula for hybrid pressure coordinate : max(p)=%f, max(pp)=%f, max(dp)%f" % (p.max(), pp.max(), dp.max()) )
return dp.max()>1e-4 # true if there is a discrepancy
return dp.max()>p0*rel_tol # true if there is a discrepancy
def compute_volume(cell_area, hlay):
cell_area = 1 # FIXME
lev = hlay.shape[0]
volume = np.zeros(hlay.shape)
for l in range(lev):
if l==0:
height = hlay[0,:,:]
else:
height = hlay[l,:,:]-hlay[l-1,:,:]
vol = cell_area * height
volume[l,:,:] = vol
return volume
def compute_mass(p, g):
ilev, nlat, nlon = p.shape
mass = np.zeros((ilev-1, nlat, nlon)) # array of air mass per cell
for i in range(ilev-1):
mass[i, :, :] = (p[i, :, :] - p[i+1, :, :]) / g
return mass
def max_volume_plot(variable_chim, variable_dyn, day_list):
GTRC1_array = []
......@@ -44,57 +64,52 @@ def max_volume_plot(variable_chim, variable_dyn, day_list):
def read_DYNAMICO(dynamico_nc, dynamico_hybrids, day=8, hour=22):
hour = 2*( (day-1)*24+hour ) # assume output every 30 min
g, p0 = 9.81, 1e5 # gravity, reference pressure for hybrid coordinate
radius, g, p0 = 6.371e6, 9.81, 1e5 # Earth radius, gravity, reference pressure for hybrid coordinate
print('Reading DYNAMICO data from %s ...'%dynamico_nc)
ds = nc.Dataset(dynamico_nc)
print(ds)
q = ds['q'][hour, 0, :, :, :].flatten()
ps = ds['ps'][hour, :, :]
phi = ds['PHI'][hour, :, :, :] # geopotential
lon, lat = ds['lon'][:], ds['lat'][:]
nlon, nlat = len(lon), len(lat)
q = ds['q'][hour, 0, :, :, :]
ps = ds['ps'][hour, :, :]
phi = ds['PHI'][hour, 1:, :, :] # geopotential'
print('shape(phi) = ', phi.shape)
lon, lat = np.meshgrid(lon, lat)
print('Min(cos(lat) = ', np.cos(lat).min() )
area = (radius**2)*np.cos(lat)*(2*np.pi/nlon)*(np.pi/nlat)
volume = compute_volume(area/g, phi)
# print('volume array length = ', len(volume), volume.size)
# print('volume array = ', volume)
print(' geopotential last hour = ', phi[:,12,27])
ds1 = nc.Dataset(dynamico_hybrids)
ap = ds1['hyai'][:].flatten() # 1D array, with ilev
bp = ds1['hybi'][:].flatten() # same
ap, bp = ds1['hyai'][:], ds1['hybi'][:]
print(' ap shape, bp shape, ps shape = ',ap.shape, bp.shape, ps.shape)
lev = len(ap) - 1
lat = ds['ps'][hour, :, :].shape[0]
lon = ds['ps'][hour, :, :].shape[1]
p = np.zeros((lev, lat, lon)) # lat changes with row, lon with column
print(' p shape, q shape = ', p.shape, ds['q'][hour, 0, :, :, :].shape)
pp = ds['P'][hour,:,12,27]
print(" Pressure read from file :", pp)
p = np.zeros((lev, nlat, nlon)) # lat changes with row, lon with column
# print(' p shape, q shape = ', p.shape, ds['q'][hour, 0, :, :, :].shape)
# pp = ds['P'][hour,:,12,27]
# print(" Pressure read from file :", pp)
if check_compute_pressure(ds1['hyam'][:], ds1['hybm'][:], p0, ps, ds['P'][hour,:,:,:] ):
print(" Discrepancy in computed pressure. Stop.")
return True
p = compute_pressure(ap,bp,p0, ps)
# for i in range (1, lev): # 0 is ground level and not corresponding to a value of ilev?
# p[i, :, :] = 10**5*ap[i] + ps*bp[i] # should return a pressure matrix(lat, lon) at each level
mass = np.zeros((lev, lat, lon)) # array of air mass per cell
volume = np.zeros((lev, lat, lon)) # array of volume per cell
for i in range (1,lev-2):
mass[i, :, :] = (p[i, :, :] - p[i+1, :, :]) / g # remove g factor?
volume[i, :, :] = (phi[i+1, :, :] - phi[i, :, :]) / g
volume = volume.flatten()
print('volume array length = ', len(volume), volume.size)
print('volume array = ', volume)
p = compute_pressure(ap, bp, p0, ps)
air_mass = compute_mass(p, g)
SO2_density = q * air_mass / volume
air_density = mass.flatten() / volume.flatten() # can i use chimere value?
SO2_density = q * air_density
return volume, SO2_density
return radius, area, volume.flatten(), SO2_density.flatten()
def read_CHIMERE(chimere_nc, day=8, hour=24):
def read_CHIMERE(dx_dy, wrf_nc, chimere_nc, day=8, hour=24):
# double airm(Time, bottom_top, south_north, west_east) ;
# airm:units = "molecule/cm**3" ;
# airm:long_name = "Air density" ;
......@@ -106,33 +121,36 @@ def read_CHIMERE(chimere_nc, day=8, hour=24):
# * we neglect horizontal variations of cell area
# => all cells have the same air mass
# * we work with molecule number rather than mass (constant factor = molar mass)
filename = chimere_nc%CHIMERE_days[day-1]
print('Reading CHIMERE data from %s ...'%filename)
ds2 = nc.Dataset(filename)
GTRC1 = ds2['GTRC1'][hour,:,:,:].flatten() # SO2 molecular mixing ratio (ppb)
air_density = ds2['airm'][hour,:,:,:].flatten() # air molecule number per unit volume
SO2_density = GTRC1 * air_density # SO2 molecule number per unit volume
print('Reading WRF data from %s ...'%wrf_nc)
wrf = nc.Dataset(wrf_nc)
cell_area = dx_dy * wrf['MAPFAC_MX'][0,:,:] * wrf['MAPFAC_MY'][0,:,:]
# *(64.066)*(1.67377*10**(-27)) molar mass x mass of 1 AMU (constant needed?) x number of air molecules per cell.
cell_mass = 1. # see FIXME above
cell_volume = cell_mass / air_density
return cell_volume, SO2_density
def volume_half_mass(cell_volume, SO2_density):
# sort SO2 density per cell from small to large
ind = np.argsort(SO2_density) # indices sorting SO2 density
sorted_mass = SO2_density[ind]
sorted_volume = cell_volume[ind]
cum_mass = np.cumsum(sorted_mass)
half_mass = 0.5*cum_mass[-1]
j = bisection_method(half_mass, cum_mass)
def getvar(var):
return ds[var][hour,:,:,:]
filename = chimere_nc%CHIMERE_days[day-1]
print('Reading CHIMERE data from %s ...'%filename)
ds = nc.Dataset(filename)
hlay = getvar('hlay') # altitude above ground of upper interface
GTRC1 = getvar('GTRC1') # SO2 molecular mixing ratio (ppb)
air_density = getvar('airm') # air molecule number per unit volume
cell_volume = compute_volume(cell_area, hlay)
SO2_density = GTRC1 * air_density # SO2 molecule number per unit volume
return cell_area, cell_volume.flatten(), SO2_density.flatten()
def volume_half_mass(volume, density, label):
amount = volume*density
# sort density per cell from small to large
ind = np.argsort(density) # indices sorting density
sorted_amount = amount[ind]
sorted_volume = volume[ind]
cum_amount = np.cumsum(amount)
half_amount = 0.5*cum_amount[-1]
j = bisection_method(half_amount, cum_amount)
volume = sorted_volume[j:-1].sum()
print('half-mass volume = ', volume)
print('(%s) half-mass volume = %d '%(label, volume))
def bisection_method(half_mass, cum_mass):
......@@ -166,18 +184,22 @@ def bisection_method(half_mass, cum_mass):
import argparse
def main():
dynamico_nc = '/data/PLT8/pub/smailler/PUY60-dynamico/dynamico.nc'
dynamico_nc = '/data/PLT8/pub/smailler/PUY60-dynamico/dynamico.nc'
dynamico_hybrids = '/data/PLT8/pub/smailler/PUY60-dynamico/apbp.nc'
data2 = read_DYNAMICO(dynamico_nc, dynamico_hybrids)
volume_half_mass_DYNAMICO= volume_half_mass(*data2)
wrf_nc = '/home/smailler/PUY60/geog_USGS_PUY60.nc'
chimere_nc = '/data/PLT8/pub/smailler/CHIMOUT-PUY60-tier2/out.201106%s00_24_PUY60-tier2.nc'
dx, dy = 6e4, 6e4 # nominal CHIMERE cell sizes in m
chimere_nc = '/data/PLT8/pub/smailler/CHIMOUT-PUY60-tier2/out.201106%s00_24_PUY60-tier2.nc'
data = read_CHIMERE(chimere_nc)
volume_half_mass_CHIMERE = volume_half_mass(*data)
radius, area_DYNAMICO, volume_DYNAMICO, density_DYNAMICO = read_DYNAMICO(dynamico_nc, dynamico_hybrids)
print('Total DYNAMICO domain area/theory =', area_DYNAMICO.sum() / (4*np.pi*radius**2) )
volume_half_mass_DYNAMICO = volume_half_mass(volume_DYNAMICO, density_DYNAMICO, 'DYNAMICO')
max_volume_plot('GTRC1', 'q', CHIMERE_days)
area_CHIMERE, volume_CHIMERE, density_CHIMERE = read_CHIMERE(dx*dy, wrf_nc, chimere_nc)
print('Total CHIMERE domain area =', area_CHIMERE.sum() )
volume_half_mass_CHIMERE = volume_half_mass(volume_CHIMERE, density_CHIMERE, 'CHIMERE')
#max_volume_plot('GTRC1', 'q', CHIMERE_days)
#plots(metrics_CHIMERE, metrics_DYNAMICO)
main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment