Source code for pycif.plugins.transforms.complex.isotopes.adjoint

import copy


[docs] def adjoint( transf, data, mapper, di, df, mode, runsubdir, workdir, **kwargs ): """Propagate two-isotopologue sensitivities back to δ and total-concentration sensitivities. The adjoint of :func:`forward`. Uses forward data stored in ``transf.fwd_data`` to compute: * **Sensitivity to total concentration**: :math:`\\partial J/\\partial C_{tot} = (a \\cdot s_{iso_2} + s_{iso_1}) / (1+a)` * **Sensitivity to δ-signature**: :math:`\\partial J/\\partial\\delta = R_{std} \\cdot C_{tot} \\cdot (s_{iso_2} - s_{iso_1}) / (1000 \\cdot (1+a)^2)` Returns immediately when ``mode != 'adj'``. Args: transf (Plugin): isotopes plugin instance (carries ``fwd_data``). data: datastore object. mapper (dict): transform mapper. di (datetime): sub-simulation start date. df (datetime): sub-simulation end date. mode (str): must be ``'adj'``; returns unchanged data otherwise. runsubdir (str): unused. workdir (str): unused. **kwargs: unused. Returns: data: updated datastore object. """ if mode != "adj": return data xmod = data.datastore inputs = transf.parameters_in.names outputs = transf.parameters_out.names unit = transf.unit r_std = transf.parameters_in.standard iso_mass = transf.parameters_out.iso_mass spec_mass = transf.parameters_out.spec_mass in_types = transf.component out_types = 2 * [transf.component[1]] for (trid, trid_out) in zip(mapper["inputs"], mapper["outputs"]): xmod[trid] = {k: xmod[trid_out][k] for k in xmod[trid_out]} xmod[trid]["adj_out"] = copy.deepcopy(xmod[trid_out]["adj_out"]) signature = transf.fwd_data["signature"] spec_data = transf.fwd_data["spec_data"] isotopologue_adj = xmod[(out_types[1], outputs[1])]["adj_out"] spec_ref_adj = xmod[(out_types[0], outputs[0])]["adj_out"] a_factor = (1 + signature / 1000) * r_std # Mass correction if units are in mass if unit == "mass": isotopologue_adj *= iso_mass[1] / spec_mass spec_ref_adj *= iso_mass[0] / spec_mass # Sensitivity to total xmod[(in_types[1], inputs[1])]["adj_out"] = ( a_factor * isotopologue_adj + spec_ref_adj ) / (1 + a_factor) # Sensitivity to signature xmod[(in_types[0], inputs[0])]["adj_out"] = ( r_std * spec_data * (isotopologue_adj - spec_ref_adj) / 1000 / (1 + a_factor) ** 2 ) del xmod[(out_types[0], outputs[0])] del xmod[(out_types[1], outputs[1])] data.datastore = xmod return data