Source code for pycif.plugins.models.dalecbethy.ini_mapper

import numpy as np
from logging import info


# Mandatory hourly variables of 'input/dynforcing.nc', see
# src/ncread_forcing.f90::ncread_dynamic_forcing. Shared with
# pycif.plugins.models.dalecbethy.io.inputs.make_forcing, which rebuilds this
# same file from these components' data-store entries.
meteo_components = [
    "swrad",
    "temperature",
    "precipitation",
    "lwdown",
    "soil_temperature",
]

# Mandatory/optional variables of 'input/staticforcing.nc', see
# src/ncread_forcing.f90::ncread_static_forcing (one canonical name kept per
# variable, even where the Fortran reader also accepts an alias). Shared with
# pycif.plugins.models.dalecbethy.io.inputs.make_forcing, which rebuilds this
# same file from these components' data-store entries.
static_components = [
    "condition_simulate",
    "pft",
    "pft_fraction",
    "lon",
    "lat",
    "soil_depth",
    "soil_texture_class",
    "B_r",
    "soil_brightness_class",
    "elevation",
    "vegetation_fraction",
]


[docs] def ini_mapper(model, general_mapper={}, backup_comps={}, transforms_order=[], ref_transform="", transform_name="", all_transforms=None, **kwargs): """Build the data-flow mapper for the D&B bottom-up CO2 flux model. Declares: * **Inputs**: - D&B's own control vector: the prior parameters read from ``input/{core,sif,lvod,slope}-params.csv`` (``src/prior.f90``), following the same ``("<model>_param", <component>)`` convention as ``satwetch4``'s ``("satwetch4_model_param", "k"/"q10")`` inputs. - The time-invariant land-surface/PFT fields read from ``input/staticforcing.nc`` (``src/ncread_forcing.f90:: ncread_static_forcing``), as ``("dalecbethy_static", <component>)``. - The hourly meteorological forcing read from ``input/dynforcing.nc`` (``src/ncread_forcing.f90:: ncread_dynamic_forcing``), as ``("meteo", <component>)``, following the same convention as ``chimere``'s/``satwetch4``'s ``("meteo", ...)`` inputs. * **Outputs** -- the NEE (net ecosystem exchange) flux computed by D&B (``src/obsop.f90``/``src/timeloop.f90``, dumped to ``diagout/dalec-bethy_{hourly,daily}-output_*.nc``, variable ``nee``, see ``src/ncwrite_output.f90``), following the same ``("flux", <component>)`` convention as ``satwetch4``'s ``("flux", "CH4_wetlands")`` output. .. warning:: TODO for a D&B developer: 1. Both the dynamic (meteo) and static forcing declared here are wired through :func:`~.io.native2inputs.native2inputs`/ :func:`~.io.inputs.make_forcing.make_meteo`/ :func:`~.io.inputs.make_forcing.make_static`, which (re)write ``input/dynforcing.nc``/``input/staticforcing.nc`` from the datastore instead of linking the original files (see :func:`~.io.inputs.make_auxiliary.make_auxiliary`, which no longer links either of them). 2. The four ``("dalecbethy_param", <kind>)`` inputs are scalar-per-PFT values (one row per ``varname``/``PFT`` pair, see the parameters CSV files), not gridded fields, so the ``gridded_netcdf`` transport used by ``satwetch4`` for ``model_param_k``/``model_param_q10`` likely needs dedicated handling in :func:`~.io.native2inputs.native2inputs` rather than applying as-is. Args: model: dalecbethy plugin instance with all date arrays set. general_mapper (dict): unused. backup_comps (dict): unused. transforms_order (list): unused. ref_transform (str): unused. transform_name (str): unused. all_transforms: unused. **kwargs: unused. Returns: dict: mapper with ``inputs`` and ``outputs``. """ input_intervals = { ddi: np.append( model.input_dates[ddi][:-1, np.newaxis], model.input_dates[ddi][1:, np.newaxis], axis=1) for ddi in model.input_dates} # Static forcing fields are time-invariant: read once, at the start of # the simulation window, following the same convention as CHIMERE's # ("inicond", s) inputs (dict_ini), which are also only needed at # model.datei. static_intervals = {model.datei: np.array([[model.datei, model.datef]])} output_intervals = { ddi: np.append( model.tstep_dates[ddi][:-1, np.newaxis], model.tstep_dates[ddi][1:, np.newaxis], axis=1) for ddi in model.tstep_dates} default_input_dict = { "input_dates": input_intervals, "force_dump": True, "domain": model.domain, "sampled": False, "sparse_data": False, "force_loadin": False, } default_static_dict = { "input_dates": static_intervals, "force_dump": True, "domain": model.domain, "sampled": False, "sparse_data": False, "force_loadin": False, } mapper = { "inputs": { # **{("dalecbethy_param", kind): default_input_dict # for kind in ("core", "sif", "lvod", "slope")}, **{("dalecbethy_static", comp): default_static_dict for comp in static_components}, **{("meteo", comp): default_input_dict for comp in meteo_components}, }, "outputs": { ("flux", comp): { "input_dates": output_intervals, "force_loadout": True, "domain": model.domain, "sampled": False, "sparse_data": False, } for comp in model.output_components }, } info("The D&B model was initialized with the following mapper:") info("\nInputs:\n\n") for key in mapper["inputs"]: info(f"\t{key}: \t {mapper['inputs'][key]}\n") info("\n\n\nOutputs:\n\n") for key in mapper["outputs"]: info(f"\t{key}: \t {mapper['outputs'][key]}\n") return mapper