Source code for pycif.plugins.models.lmdz_ico.io.outputs.make_adjoint_out

from pathlib import Path

import numpy as np
import pandas as pd
import xarray as xr

from ...chemistry import (
    BOLTZMAN,
    compute_chemistry_step_ad,
    parse_chemical_scheme,
    read_kinetic,
    read_prescr,
)
from .fake_end import read_air_mass
from ......utils.hdf5 import _hdf5_lock


[docs] def make_adjoint_out(self, runsubdir, ddi, ref_fwd_dir): runsubdir = Path(runsubdir) ref_fwd_dir = Path(ref_fwd_dir) # Dimensions nspec = len(self.chemistry.active_species) nlev = self.domain.nlev nlat = self.domain.nlat nlon = self.domain.nlon if not hasattr(self.domain, "areas"): self.domain.calc_areas() area = self.domain.areas # Fetch initial conditions from reference forward inicond = xr.DataArray( data=np.zeros((nspec, nlev, nlat, nlon)), dims=["spec", "lev", "lat", "lon"], ) inicond_file = ref_fwd_dir / ddi.strftime("%Y-%m-%d_%H-%M") / "start.nc" with _hdf5_lock: with xr.open_dataset(inicond_file) as ds: for index, spec in enumerate(self.chemistry.active_species): inicond[index, ...] = ds[spec].values # Read mass of air in the atmosphere and increase precision mass = read_air_mass(self, ddi, runsubdir).isel(time=0) # Read adjoint sensitivity at beginning of run if ddi != self.subsimu_dates[-2]: sum_mass = float(mass.sum()) # Parsing schemical scheme reaction_list, molar_masses = parse_chemical_scheme(self) # Reading kinetic.nc, dims: (time, lev, lat, lon) kinetic = read_kinetic(self, ddi, runsubdir) ref_pmid, ref_temp = kinetic.pmid, kinetic.temp # Reading prescr_*.nc, dims: (spec, time, lev, lat, lon) [molec/cm3] ref_prescr = read_prescr(self, ddi, runsubdir) ref_prescr = ref_prescr * ref_pmid / (BOLTZMAN * ref_temp) * 1.0e-6 inicond_ad = xr.DataArray( data=np.zeros((nspec, nlev, nlat, nlon)), dims=["spec", "lev", "lat", "lon"], ) sensit_start_file = runsubdir / "start.nc" with _hdf5_lock: with xr.open_dataset(sensit_start_file) as ds_ini: for index, spec in enumerate(self.chemistry.active_species): inicond_ad[index, ...] = ds[spec].values ref_sensit = inicond_ad.sum(["lev", "lat", "lon"]) / sum_mass mmr_ad = compute_chemistry_step_ad( reaction_list, molar_masses, 3600 * 24 * pd.to_datetime(ddi).days_in_month, inicond, inicond_ad, ref_prescr.isel(time=0), ref_pmid.isel(time=0), ref_temp.isel(time=0), ) ini_chem_sensit = mmr_ad.sum(["lev", "lat", "lon"]) else: ref_sensit = xr.DataArray(data=np.zeros(nspec), dims=["spec"]) ini_chem_sensit = xr.DataArray(data=np.zeros(nspec), dims=["spec"]) # Put adjoint sensitivities to zero or propagate previous values ds_ini = xr.Dataset( { spec: mass * ref_sensit[index] + ini_chem_sensit[index] for index, spec in enumerate(self.chemistry.active_species) } ) with _hdf5_lock: ds_ini.to_netcdf(runsubdir / "restart.nc") # Fluxes ntime = len(self.flx_input_dates[ddi]) - 1 ones = xr.DataArray( data=np.ones((ntime, nlat, nlon)), dims=["time", "lat", "lon"], ) dt = pd.to_timedelta(self.flx_tresol).total_seconds() ds_flux = xr.Dataset( { spec: ones * ref_sensit[index] * dt * area[np.newaxis, ...] for index, spec in enumerate(self.chemistry.emitted_species) } ) with _hdf5_lock: ds_flux.to_netcdf(runsubdir / "flux_out.nc") ntime = len(self.input_dates[ddi]) - 1 zeros = xr.DataArray( data=np.zeros((ntime, nlev, nlat, nlon)), dims=["time", "lev", "lat", "lon"], ) # Prescribed concentrations ds_prescr = xr.Dataset({spec: zeros for spec in self.chemistry.prescribed_species}) with _hdf5_lock: ds_prescr.to_netcdf(runsubdir / "prescr_out.nc") # Prodloss ds_prodloss = xr.Dataset({spec: zeros for spec in self.chemistry.prodloss_species}) with _hdf5_lock: ds_prodloss.to_netcdf(runsubdir / "prodloss3d_out.nc")