One thing that seems logical to me is that set_value should be undefined/throw an error for variables which are output variables but not input variables, i.e., if some variable name x where x in model.get_output_var_names() and x not in model.get_input_var_names() then model.set_value(x, value) should fail. However, the documentation doesn’t say this.
It feels that a dual also makes sense, if a variable is purely an input, and not an output, then get_value on that variable should throw an error. Is this what we expect and if so should it be more clear in the documentation and in the bmi-tester? Or are things more permissive?
That all makes sense, but I bet there is some quirky workflow that we can think up that would violate this! Having said that, everything I try to think of has an easy (and preferable) workaround. Not sure I agree about get_value though, I don’t see anything particularly problematic about getting an input variable. E.g. if your model reads data from a file and you want to know what one of those variables is outside of the model.
Maybe this discussion is in scope for the v3 roadmap?
@dorchard I agree. If set_value is called with the name of an output-only variable, it should raise an error—just as it would for an unrecognized name. In fact, this is how I’ve seen most BMIs implemented.
As for whether input variables can be passed to get_value, we’ve gone back and forth on this. My view is that if you want to expose an input variable as an output, then it should be listed explicitly as both an input and an output variable. We’ve seen cases where a model accepts an input array but doesn’t store it internally as a simple flat array; sometimes calculations are performed on the input before storing it in a different form. In those cases, making the input variable also available as an output requires additional code to reconstruct a flat array from the internal data structures.
If we wanted input variables to implicitly double as output variables, the spec would need to require that all input variables must be exposed this way. To me, that seems like it could be too much to ask—at least in some cases.
The philosophical answer is simply that BMI is more descriptive than prescriptive. It sketches out the behaviors and expectations that are useful for various desired modes of coupling and other inter-operation, and otherwise doesn’t particularly specify how models are supposed to work.
Your wording does suggest something to me that probably should get written into BMIv3, and maybe even a revision to BMIv2 - various classes of errors that models need to actually handle, rather than resulting in language-level undefined behavior (in C, C++, and the equivalent in Fortran). Particularly, passing a variable name that’s invalid for a given routine, or simply calling a routine that the model doesn’t implement.