Source code for pycif.plugins.transforms.system.loadfromoutputs.adjoint

from logging import info
import copy
import pandas as pd
import numpy as np
from .....utils.datastores.empty import init_empty


[docs] def adjoint( transform, inout_datastore, controlvect, obsvect, mapper, di, df, mode, runsubdir, workdir, onlyinit=False, do_simu=True, check_transforms=False, **kwargs ): """Write model-space adjoint sensitivities to native model input format. The adjoint of :func:`forward`: for each input tracer, collects the adjoint sensitivity arrays from the output datastore (populated by ``array2sampled`` or ``sparse2sample``), initialises empty datastores where data is absent, and calls the model's ``outputs2native_adj`` function to write the sensitivities to the model-native format. Also performs a deep copy of the ``'inputs'`` datastore to prevent later in-place modifications from corrupting the adjoint pass. Batch-sampling tracers (``__sample#N`` naming) are grouped and processed together via ``trids_in_ref`` to avoid redundant I/O. Args: transform (Plugin): loadfromoutputs instance (carries ``outputs2native_adj``). inout_datastore (dict): mutable datastore; ``'outputs'`` holds the sensitivities; ``'inputs'`` is updated in-place. controlvect: unused. obsvect: unused. mapper (dict): transform mapper. di (datetime): sub-simulation start date. df (datetime): sub-simulation end date. mode (str): ``'adj'``. runsubdir (str): passed to ``outputs2native_adj``. workdir (str): unused. onlyinit (bool): forwarded to ``outputs2native_adj``. do_simu (bool): forwarded to ``outputs2native_adj``. check_transforms (bool): forwarded to ``outputs2native_adj``. **kwargs: unused. """ datastore = inout_datastore["outputs"] trids_in = list(mapper["inputs"].keys()) trids_in_ref = list(set( [(trid[0], trid[1].split("__sample#")[0]) for trid in trids_in])) for trid in trids_in_ref: input_type = trid[0] # Batch dump if any trids2dump = [ tr for tr in trids_in if tr[1].split("__sample#")[0] == trid[1] ] # If input parameter is '', # dumps all available parameters of this component if trid[1] == "": trids2dump = [t for t in datastore if t[0] == trid[0]] # Initialize empty datastore if empty data2dump = {} for t in trids2dump: data2dump[t] = {} for di in datastore.get(t, {}): if len(datastore[t][di]) == 0: data2dump[t][di] = init_empty() continue data2dump[t][di] = datastore[t][di] # Store to input datastore inout_datastore["inputs"].update(data2dump) # Dump to model inputs transform.outputs2native_adj( data2dump, input_type, di, df, runsubdir, mode, onlyinit=onlyinit, do_simu=do_simu, check_transforms=check_transforms ) # Hard save input inout_datastore["inputs"] = copy.deepcopy(inout_datastore["inputs"])