import numpy as np
[docs]
def ini_mapper(model, general_mapper={}, backup_comps={},
transforms_order=[], ref_transform="", **kwargs):
"""
PURPOSE
The ini_mapper function is mandatory to make a model work. It informs pycif
about the inputs and outputs of the model. It should return a so-called
"mapper". A mapper is a dictionary with two keys:
*) inputs: all the inputs for the model (fluxes, meteo, chemical fields,
executables, parameter files, etc)
*) outputs: all the outputs; in our cases, concentrations (concs)
Both inputs and outputs keys are them selves dictionaries. Their format is:
*) ("type", "parameter"): {information dictionary}
The pair ("type", "parameter") should cover all the necessary inputs
and outputs. In the case when no "parameter" is relevant, and empty string
can be specified.
The information dictionary can include the following information, depending
on your model:
*) input_dates: all dates at which the model expects some inputs for the
given type/parameter; e.g., if TM5 needs 3-hourly meteo fields,
input_dates will be the list of all dates in the simulation period with
a frequency of 3H; it is recommended to initiate this variable in the
function ini_periods, that initiates all date related variables for your
model
*) domain: usually the same as the model domain
*) force_dump: True if the given type/parameter should be dumped before
running the model executable
*) any other parameter that can be used in the native2inputs / outputs2native
functions.
IN/OUT
none
KWARGS
none
ASSUMPTIONS
none
EXCEPTIONS
When this function encounters a problem that it cannot solve,
it will raise a RuntimeError. Pythons exeception handling will
provide a traceback, including files, calls and line numbers.
PYTHON VERSION
3.7.5
VERSION CHANGE HISTORY
1.0 18-09-2020 by J.C.A. van Peet.
Original code.
"""
# Input needs to be defined as intervals
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}
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.input_dates}
# For now, define an empty mapper
mapper = {"inputs": {}, "outputs": {}}
# Should look like something:
# Input keys are used in io/mative2inputs
# Output keys are used in io/output2native
default_dict = {"input_dates": input_intervals,
"force_dump": True,
"sparse_data": False,
"sampled": False}
dict_surface = dict(
default_dict,
**{"domain": model.domain,
"fixed_domain": True})
dict_meteo = dict(
dict_surface,
**{"force_loadin": False}
)
dict_ini = dict(
dict_surface,
**{"input_dates": {
model.datei: np.array([[model.datei, model.datei]])},
"force_loadin": False}
)
mapper = {
"inputs": {
("meteo", ""): dict_meteo, # Meteo files
("flux", "CH4"): default_dict, # emission file
# ("chemistry", "CH4"): default_dict, # Source/sink files
("inicond", "CH4"): dict_ini, # Source/sink files
},
"outputs": {
# JvP 20210617: Apparently, when the keyword is "concs", the
# function being called is outputs2native_adj.py, which then
# calls make_obs.py that creates the observations for input
# into TM5. For more info, see mail by Antoine Berchet,
# dd. 16-06-2021.
("concs", s): {"isobs": True, "force_loadout": True,
"input_dates": output_intervals,
"domain": model.domain,
"sampled": True,
"sparse_data": False
}
for s in ["CH4"] # Make it more general later
},
}
# Return the mapper
return mapper
# end def ini_mapper