When putting together a Model containing a DataComponent, the instantiation fails because it finds a mismatch between the outwards of the DataComponent and the inwards of a "real" Component. For example, if subsurface is a successfully instantiated DataComponent and openwater is some successfully instantiated OpenWaterComponent, the following error message is thrown:
File ~/anaconda3/envs/unifhy/lib/python3.9/site-packages/unifhy/model.py:126, in Model._check_components_plugging(self)
123 print(src.outwards_info)
124 if (trf not in src.outwards_info
125 or cat not in src.outwards_info[trf]['to']):
--> 126 raise RuntimeError(
127 f"{cat} component inward transfer '{trf}' "
128 f"not available from {src.category} component"
129 )
RuntimeError: openwater component inward transfer 'surface_runoff_flux_delivered_to_rivers' not available from subsurface component
I believe that this behaviour exists since https://github.com/unifhy-org/unifhy/pull/76. This is due to the fact that the framework components SurfaceLayerComponent/SubSurfaceComponent/OpenWaterComponent define their interfaces in their _inwards_info and _outwards_info, but they do not assign anything to their _inwards and _outwards attributes (which are the new attributes introduced in #76 to allow contributors to create components only featuring subsets of the inwards/outwards). But then the property outwards_info of MetaComponent has a condition to only return those outwards that are actually produced by the component (as listed in _outwards attribute), see: https://github.com/unifhy-org/unifhy/blob/26fa890c524b2815edaaa012d157511e098f1d2c/unifhy/component.py#L61-L66
So for the case of a DataComponent getting its outwards and outwards_info from the substituted component, i.e. either SurfaceLayerComponent, SubSurfaceComponent, or OpenWaterComponent, it gets an empty dict for outwards even though it is getting a non empty outwards_info. This is why the metaclass property returns an empty dictionary too.
When putting together a
Model
containing aDataComponent
, the instantiation fails because it finds a mismatch between the outwards of the DataComponent and the inwards of a "real" Component. For example, if subsurface is a successfully instantiatedDataComponent
and openwater is some successfully instantiatedOpenWaterComponent
, the following error message is thrown:I believe that this behaviour exists since https://github.com/unifhy-org/unifhy/pull/76. This is due to the fact that the framework components
SurfaceLayerComponent
/SubSurfaceComponent
/OpenWaterComponent
define their interfaces in their_inwards_info
and_outwards_info
, but they do not assign anything to their_inwards
and_outwards
attributes (which are the new attributes introduced in #76 to allow contributors to create components only featuring subsets of the inwards/outwards). But then the propertyoutwards_info
ofMetaComponent
has a condition to only return those outwards that are actually produced by the component (as listed in_outwards
attribute), see: https://github.com/unifhy-org/unifhy/blob/26fa890c524b2815edaaa012d157511e098f1d2c/unifhy/component.py#L61-L66So for the case of a
DataComponent
getting its outwards and outwards_info from the substituted component, i.e. eitherSurfaceLayerComponent
,SubSurfaceComponent
, orOpenWaterComponent
, it gets an empty dict for outwards even though it is getting a non empty outwards_info. This is why the metaclass property returns an empty dictionary too.This behaviour has not been picked up by the unit tests because the DataComponent we use in there are substituting for our dummy Components whose interfaces are intentionally overwritten, and unlike in the actual framework components,
_inwards
and_outwards
are populated this time, see e.g.: https://github.com/unifhy-org/unifhy/blob/26fa890c524b2815edaaa012d157511e098f1d2c/tests/tests/components/surfacelayer/dummy.py#L50-L58Credit and thank you go to @mattjbr123 for reporting and diagnosing this one.