pycif.plugins.models.dalecbethy — API reference#
Configuration reference: dalecbethy plugin
- pycif.plugins.models.dalecbethy.ini_mapper.ini_mapper(model, general_mapper={}, backup_comps={}, transforms_order=[], ref_transform='', transform_name='', all_transforms=None, **kwargs)[source]#
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 assatwetch4’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 aschimere’s/satwetch4’s("meteo", ...)inputs.
Outputs – the NEE (net ecosystem exchange) flux computed by D&B (
src/obsop.f90/src/timeloop.f90, dumped todiagout/dalec-bethy_{hourly,daily}-output_*.nc, variablenee, seesrc/ncwrite_output.f90), following the same("flux", <component>)convention assatwetch4’s("flux", "CH4_wetlands")output.
Warning
TODO for a D&B developer:
Both the dynamic (meteo) and static forcing declared here are wired through
native2inputs()/make_meteo()/make_static(), which (re)writeinput/dynforcing.nc/input/staticforcing.ncfrom the datastore instead of linking the original files (seemake_auxiliary(), which no longer links either of them).The four
("dalecbethy_param", <kind>)inputs are scalar-per-PFT values (one row pervarname/PFTpair, see the parameters CSV files), not gridded fields, so thegridded_netcdftransport used bysatwetch4formodel_param_k/model_param_q10likely needs dedicated handling innative2inputs()rather than applying as-is.
- Parameters:
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:
mapper with
inputsandoutputs.- Return type:
dict
- pycif.plugins.models.dalecbethy.ini_periods.ini_periods(self, **kwargs)[source]#
Define D&B’s temporal splitting variables.
Sets
subsimu_dates,tstep_datesandinput_datesfollowing thetemplate/satwetch4convention.Warning
TODO for a D&B developer: D&B’s simulation window (
yyyymmdd_start/yyyymmdd_end) and internal hourly time step are compiled into the executable viasrc/dimensions.f90(itself generated fromutil/templates/dimensions.f90.templatebyutil/model_setup.pyatmaketime, seecompile.py). D&B therefore cannot, as of today, be split into several independently-run pyCIF sub-simulations without triggering a recompilation for each one (unlike e.g. CHIMERE, which reads its simulation window from a runtime namelist).Until this is resolved (either by adding a runtime override to D&B, or by re-triggering
compile()for every sub-period), this function defines a single sub-simulation spanning the full[datei, datef]pyCIF window, and internal time steps at hourly resolution (D&B’s native resolution, seesrc/dimensions.f90:nhour = nday*24), regardless ofoutput_resolution.- Parameters:
self – the dalecbethy model Plugin.
**kwargs – unused.
- pycif.plugins.models.dalecbethy.run.run(self, runsubdir, mode, workdir, ddi, nbproc=1, do_simu=True, approx_transf=False, ref_fwd_dir='', overlap=False, datastore=None, **kwargs)[source]#
Compile (if needed) and run the D&B executable for one sub-period.
D&B is a self-contained Fortran executable (not a Python model like
satwetch4): this function launches it as a subprocess inrunsubdir, wheremake_auxiliary()andnative2inputs()are expected to have already staged everything the executable needs (input/*.nc,input/*-params.csv,opt.nml,obs.nml), following the fixed, hard-wired relative paths used throughout the D&B sources (see e.g.src/prior.f90,src/ncread_forcing.f90:input/...,mode==adjis not implemented yet.This function also triggers
compile()itself, on the first call only (i.e. onceself.workdir/model/runmodel.xexists, later calls skip straight to running it). It is deliberately not triggered any earlier – e.g. by the generic, input-agnosticrun_modeltransform init (see the__init__.pynote) – because D&B’s build needsrunsubdir/input/{static,dyn}forcing.ncto already exist (seecompile()); by the timerunis first called, pyCIF has finished initialising the model (domain, mapper, periods) and staging its input data (vianative2inputs()), so that precondition holds.- Parameters:
self – the dalecbethy model Plugin.
runsubdir (str) – working directory for the current run; the D&B executable and its
input/directory must be staged here.mode (str) – ‘fwd’, ‘tl’ or ‘adj’.
workdir (str) – pyCIF working directory.
ddi (datetime.datetime) – start date of the current sub-simulation.
do_simu (bool) – re-run or not an existing simulation.
Warning
TODO / open questions for a D&B developer:
D&B ships a hand-coded adjoint (
src/cost_bw.f90,runassi.x) but it is wired to D&B’s own L-BFGS-B minimiser (mini/), driving D&B’s internal control vector (src/prior.f90) against D&B’s own observation operator (src/obsop.f90), not to a per-timestep tangent-linear/adjoint call pyCIF could drive itself (unlike e.g. CHIMERE’stlchimere.e/achimere.e). Whether/how a pyCIF-drivenmode='tl'/'adj'run should be implemented here (e.g. by building and callingrunassi.xor a new dedicated driver) is left as a follow-up.D&B currently only supports full-domain runs at hourly internal time steps between
yyyymmdd_start/yyyymmdd_end(src/dimensions.f90); how that maps onto pyCIF’s sub-simulation windows (ddi/ddf) still needs to be decided, in particular since those dates are presently compiled into the executable rather than passed at runtime.
- pycif.plugins.models.dalecbethy.utils.compile(self, runsubdir)[source]#
Compile (or copy) the D&B forward executable (
runmodel.x).Follows the same two-strategy approach as the
chimereplugin:Copy a pre-built executable (default) – copies
runmodel.xfromself.direxecinto$workdir/model/. Skipped whenforce-recompile = True.Compile from sources – triggered when
auto-recompile = True(or when no pre-built executable is found). Clones the source tree fromself.dir_sources(which should point tomodel_sources/dalecbethy, i.e. the unmodified mirror of/home/chimereges/aberchet/DB/model/sites), links the compiler configuration file (mk.compile->config/mk.compile-<compiler>, see the D&BREADME), linksrunsubdir’s already-stagedinput/{static,dyn}forcing.ncinto the source tree, and runsmake runmodel.x DOMAIN=<domain_name>.
Note
D&B’s
runmodel.xtarget does not merely link object files: it transitively depends onsrc/dimensions.f90, which the Makefile regenerates (viautil/model_setup.py) from the actual$(INDIR)/{static,dyn}forcing.ncfiles, i.e.input/staticforcing.nc/input/dynforcing.nc(see the Makefile rule for$(SRCDIR)/dimensions.f90and the$(FORCE_STATIC)/$(FORCE_DYN)targets). Those are exactly the filesnative2inputs()already wrote torunsubdir/input/beforerun()gets here, so this function links them straight intosources/input/under the same names, which pre-satisfies the$(FORCE_STATIC)/$(FORCE_DYN)targets and short-circuits the Makefile’s ownforcing/<domain_name>_{static,dyn}forcing*.nclookup. This is also whyrun()– not the generic, input-agnosticrun_modeltransform init – is what triggers this function:runsubdir/inputmust already hold the real, resolved forcing files for the compile to succeed.The prior parameter CSVs (
parameters/<domain_name>-*-params.csv) do not need the same treatment: they are small enough to be part of the trackedmodel_sources/dalecbethy/parametersmirror already, so the Makefile’s own$(INDIR)/%params.csvrule resolves them directly from the copied source tree.Warning
TODO / open question for a D&B developer: the tangent-linear/adjoint executable is only built by the
xassi/libstargets (libadstack-$(FC).a,libmini-$(FC).a,cost_bw.f90); this is not wired up here yet since D&B’s own TL/adjoint currently only feeds its internal L-BFGS-B minimiser (make xassi), not a pyCIF-driven tl/adj run.- Parameters:
self (Plugin) – dalecbethy model plugin instance (carries
workdir,direxec,dir_sources,domain_name,force-recompile/auto-recompileflags).runsubdir (str) – sub-directory of the simulation that triggered this (lazy, first-call-only) compilation; its
input/directory is expected to already holdstaticforcing.nc/dynforcing.nc, as staged bynative2inputs().
- Raises:
CifRuntimeError – if
auto-recompileis False and no executable can be found indirexec.
- pycif.plugins.models.dalecbethy.io.native2inputs.native2inputs(self, datastore, input_type, datei, datef, runsubdir, mode='fwd', onlyinit=False, do_simu=True, check_transforms=False, **kwargs)[source]#
Converts data at the model data resolution to D&B-compatible input files.
Mirrors
pycif.plugins.models.chimere.io.native2inputs.native2inputs: dispatches oninput_typeto a dedicatedmake_<type>function."meteo"(D&B’sinput/dynforcing.nc) and"dalecbethy_static"(input/staticforcing.nc) are wired so far, perrequired_inputsin the package__init__.py(see theini_mapper.pyTODO for the still-unwired"dalecbethy_param"component type).- Parameters:
self – the dalecbethy model Plugin.
datastore – data to convert.
input_type (str) – the component type to convert;
"meteo"and"dalecbethy_static"are handled.datei – date interval of the sub-simulation.
datef – date interval of the sub-simulation.
runsubdir (str) – sub-directory for the current simulation.
mode (str) – running mode: one of ‘fwd’, ‘adj’ and ‘tl’.
onlyinit (bool) – unused, kept for interface compatibility.
do_simu (bool) – if False, the simulation does not need to be run.
check_transforms (bool) – unused, kept for interface compatibility.
**kwargs – unused, kept for interface compatibility.
- pycif.plugins.models.dalecbethy.io.native2inputs_adj.native2inputs_adj(self, datastore, input_type, datei, datef, runsubdir, mode='fwd', check_transforms=False, **kwargs)[source]#
Read adjoint sensitivities and format them to pyCIF data format.
Warning
Not implemented: D&B’s adjoint (
src/cost_bw.f90) is currently only wired to D&B’s own internal minimiser (make xassi, see the TODO inrun.py), not to a pyCIF-driven adjoint run. There is therefore nothing to convert here yet.- Parameters:
self – the dalecbethy model Plugin.
input_type (str) – component name.
datastore – data to convert.
datei – date interval of the sub-simulation.
datef – date interval of the sub-simulation.
mode (str) – running mode: one of ‘fwd’, ‘adj’ and ‘tl’.
runsubdir (str) – sub-directory for the current simulation.
- pycif.plugins.models.dalecbethy.io.outputs2native.outputs2native(self, data2dump, input_type, di, df, runsubdir, mode='fwd', onlyinit=False, check_transforms=False, **kwargs)[source]#
Read D&B NetCDF diagnostics back into pyCIF objects.
D&B writes its diagnostics to
diagout/dalec-bethy_{hourly,daily}-output_<yyyymmdd_start>-<yyyymmdd_end>.nc(seesrc/ncwrite_output.f90), on thenspsample-point dimension (grid-cell x active-PFT combinations, seesrc/dimensions.f90). The stream (hourly/daily) to read is controlled byself.output_resolution.The output file also carries, on that same
nspdimension, thegidx(1-based grid-cell index, D&B’smap_sample2grid) andpft_fraction(D&B’sfracv) static fields. These are used here to recombine the PFT-level sample points of each grid cell into a single per-cell value (apft_fraction-weighted average), so the result lines up with the pyCIFdomainbuilt bypycif.plugins.domains.dalecbethy.read_domain(domain.active, on the same grid-cell indexing asgidx).- Parameters:
self – the dalecbethy model Plugin.
data2dump (dict) – output data structure to fill for every component/tracer declared in the mapper.
input_type (str) – the type of model outputs to be processed (redundant with the components of
data2dump).di (datetime.datetime) – start/end date of the present sub-simulation.
df (datetime.datetime) – start/end date of the present sub-simulation.
runsubdir (str) – path to the present sub-simulation work directory.
mode (str) – running mode; one of “fwd”, “tl” and “adj”.
- Returns:
a dictionary with structure the components/tracers to be extracted, with each component’s per-grid-cell
xarray.DataArray(PFT sample points recombined ontoself.domain’s grid cells).- Return type:
dict
- pycif.plugins.models.dalecbethy.io.outputs2native_adj.outputs2native_adj(self, data2dump, input_type, di, df, runsubdir, mode='fwd', onlyinit=False, do_simu=True, check_transforms=False, **kwargs)[source]#
Save adjoint-forcing information for a later adjoint D&B call.
Warning
Not implemented: see the
run.pyTODO – D&B’s adjoint is not yet wired to be driven step-by-step from pyCIF.- Parameters:
self – the dalecbethy model Plugin.
data2dump (dict) – concentration/flux data for each component.
input_type (str) – the type of model outputs to be processed.
di (datetime.datetime) – start/end date of the present sub-simulation.
df (datetime.datetime) – start/end date of the present sub-simulation.
runsubdir (str) – path to the present sub-simulation work directory.
mode (str) – running mode; one of “fwd”, “tl” and “adj”.
- pycif.plugins.models.dalecbethy.io.inputs.make_auxiliary.make_auxiliary(self, ddi, runsubdir, do_simu=True, mode='fwd', **kwargs)[source]#
Stage every file D&B’s
runmodel.xexpects, inrunsubdir.D&B hard-wires relative input paths in its Fortran sources (e.g.
src/prior.f90:input/core-params.csv;src/ncread_forcing.f90:input/staticforcing.nc,input/dynforcing.nc;src/obs.f90:obs.nml), so this function must reproduce, insiderunsubdir, the same layout as the reference D&B checkout (see theJobs/Makefile“model_input” target for the equivalent shell-level logic):neither
runsubdir/input/staticforcing.ncnorrunsubdir/input/dynforcing.ncare linked here: both are (re)written per sub-simulation, from the("dalecbethy_static", <component>)/("meteo", <component>)data-store entries, bynative2inputs()/make_static()/make_meteo()(seepycif.plugins.models.dalecbethy.ini_mapper.ini_mapper());link the four prior-parameter CSV files for
self.domain_name(fromself.parameters_dir) torunsubdir/input/{core,sif,lvod,slope}-params.csv;write
runsubdir/obs.nml(see_OBS_NML_DEFAULTS);create the (empty)
runsubdir/diagoutdirectory D&B writes its NetCDF diagnostics to.
The compiled executable itself is staged into
runsubdirbyrun(), not here –run.runis also what lazily triggerscompile()on first use (see the package__init__.pynote on why compilation cannot happen any earlier).- Parameters:
self – the dalecbethy model plugin.
ddi (datetime.datetime) – start date of the present simulation period.
runsubdir (str) – path to the current sub-simulation work directory.
do_simu (bool) – if False, the simulation does not need to be run.
mode (str) – the running mode (‘fwd’, ‘tl’, ‘adj’).
- pycif.plugins.models.dalecbethy.io.inputs.make_forcing.make_meteo(self, datastore, runsubdir, mode, datei, datef)[source]#
Build D&B’s
input/dynforcing.ncfrom themeteodata-store.See
_make_forcing()for the shared logic (also used bymake_static()): for each of D&B’s mandatory hourly meteo components (seepycif.plugins.models.dalecbethy.ini_mapper.meteo_components), either the raw forcing file is linked as-is, or the component is (re)written viaself.meteo.write. The mandatoryyyyymmddhhcalendar variable – not itself a per-component mapper input – is then copied as-is from the original raw file, for the hours covered by[datei, datef].- Parameters:
self – the dalecbethy model Plugin.
datastore (dict) – the pyCIF data-store, keyed by
("meteo", <component>).runsubdir (str) – sub-directory for the current simulation.
mode (str) – running mode (‘fwd’, ‘tl’, ‘adj’); only ‘fwd’ is supported so far (D&B has no adjoint/tangent-linear wiring for meteo yet).
datei – date interval of the sub-simulation.
datef – date interval of the sub-simulation.
- Raises:
NotImplementedError – if
mode != "fwd".
- pycif.plugins.models.dalecbethy.io.inputs.make_forcing.make_static(self, datastore, runsubdir, mode, datei, datef)[source]#
Build D&B’s
input/staticforcing.ncfrom thedalecbethy_staticdata-store.See
_make_forcing()for the shared logic (also used bymake_meteo()): for each of D&B’s time-invariant land-surface/PFT components (seepycif.plugins.models.dalecbethy.ini_mapper.static_components), either the raw forcing file is linked as-is, or the component is (re)written viaself.static.write. Unlikedynforcing.nc, there is noyyyymmddhhcalendar variable to copy.- Parameters:
self – the dalecbethy model Plugin.
datastore (dict) – the pyCIF data-store, keyed by
("dalecbethy_static", <component>).runsubdir (str) – sub-directory for the current simulation.
mode (str) – running mode (‘fwd’, ‘tl’, ‘adj’); only ‘fwd’ is supported so far (D&B has no adjoint/tangent-linear wiring for static forcing yet).
datei – date interval of the sub-simulation.
datef – date interval of the sub-simulation.
- Raises:
NotImplementedError – if
mode != "fwd".
- pycif.plugins.models.dalecbethy.io.inputs.utils.find_unique_match(directory, pattern)[source]#
Find the single file matching
patternindirectory.- Parameters:
directory (str) – directory to search in.
pattern (str) – a
globpattern.
- Returns:
the single matching file path.
- Return type:
str
- Raises:
FileNotFoundError – if zero, or more than one, file matches.