import xarray as xr
import numpy as np
from ......utils.hdf5 import _hdf5_lock
[docs]
def make_aout(self, runsubdir, ddi):
"""Create zeroed adjoint output files expected by the CHIMERE adjoint executable.
Writes four NetCDF3 CLASSIC files into *runsubdir*:
* ``aout.aemis.nc`` — adjoint sensitivities w.r.t. anthropogenic
emissions; shape ``(nhours+1, nlevemis, nlat, nlon)`` per species.
* ``aout.bemis.nc`` — adjoint sensitivities w.r.t. biogenic emissions;
shape ``(nhours+1, nlevemis_bio, nlat, nlon)`` per species.
* ``aout.ini.nc`` — adjoint sensitivities w.r.t. initial concentrations;
shape ``(nivout, nlat, nlon)`` per species.
* ``aout.bc.nc`` — adjoint sensitivities w.r.t. boundary conditions;
contains ``top_conc`` and ``lat_conc`` tensors.
All arrays are initialised to zero; the CHIMERE adjoint executable
accumulates sensitivities into them during the backward run.
Args:
self: CHIMERE model plugin instance (carries ``domain``,
``chemistry.acspecies``, ``chemistry.emis_species``,
``chemistry.bio_species``, ``nhours``, ``nlevemis``,
``nlevemis_bio``, ``nivout``).
runsubdir (str): path to the period run directory.
ddi (datetime): period start date (unused; kept for API symmetry
with other io functions).
"""
# Domain
domain = self.domain
# Active species
acspec = self.chemistry.acspecies.attributes[:]
aemis_species = self.chemistry.emis_species.attributes[:]
bemis_species = self.chemistry.bio_species.attributes[:]
# Aout.aemis.nc
ds = xr.Dataset(
{s: (("Time", "bottom_top", "south_north", "west_east"),
np.zeros((self.nhours + 1, self.nlevemis, domain.nlat, domain.nlon)))
for s in aemis_species}
)
spec_dtype = np.dtype(('S', 23))
ds["species"] = xr.DataArray(
[s.ljust(23) for s in aemis_species], dims=["Species"]).astype(spec_dtype)
with _hdf5_lock:
ds.to_netcdf(f"{runsubdir}/aout.aemis.nc", "w", format="NETCDF3_CLASSIC",
encoding={'species': {'char_dim_name': 'SpStrLen'}})
# Aout.bemis.nc
ds = xr.Dataset(
{s: (("Time", "bottom_top", "south_north", "west_east"),
np.zeros((self.nhours + 1, self.nlevemis_bio, domain.nlat, domain.nlon)))
for s in bemis_species}
)
spec_dtype = np.dtype(('S', 23))
ds["species"] = xr.DataArray(
[s.ljust(23) for s in bemis_species], dims=["Species"]).astype(spec_dtype)
with _hdf5_lock:
ds.to_netcdf(f"{runsubdir}/aout.bemis.nc", "w", format="NETCDF3_CLASSIC",
encoding={'species': {'char_dim_name': 'SpStrLen'}})
# Aout.ini.nc
ds = xr.Dataset(
{s: (("bottom_top", "south_north", "west_east"),
np.zeros((self.nivout, domain.nlat, domain.nlon)))
for s in acspec}
)
spec_dtype = np.dtype(('S', 23))
ds["species"] = xr.DataArray(
[s.ljust(23) for s in acspec], dims=["Species"]).astype(spec_dtype)
with _hdf5_lock:
ds.to_netcdf(f"{runsubdir}/aout.ini.nc", "w", format="NETCDF3_CLASSIC",
encoding={'species': {'char_dim_name': 'SpStrLen'}})
# Aout.bc.nc
ds = xr.Dataset({
"top_conc": (("Time", "south_north", "west_east", "Species"),
np.zeros((self.nhours + 1, domain.nlat, domain.nlon, len(acspec)))),
"lat_conc": (("Time", "bottom_top", "h_boundary", "Species"),
np.zeros((self.nhours + 1, self.nivout,
domain.nlon_side, len(acspec))))
})
spec_dtype = np.dtype(('S', 23))
ds["species"] = xr.DataArray(
[s.ljust(23) for s in acspec], dims=["Species"]).astype(spec_dtype)
with _hdf5_lock:
ds.to_netcdf(f"{runsubdir}/aout.bc.nc", "w", format="NETCDF3_CLASSIC",
encoding={'species': {'char_dim_name': 'SpStrLen'}})