feat: add separateAllVarsWithDims option to spec file to separate all vars with a dimension on the LHS#602
Conversation
separateAllVarsWithDims option to spec file to separate all vars with a dimension on the LHS
chrispcampbell
left a comment
There was a problem hiding this comment.
@ToddFincannonEI: I pushed some additional tests and comment changes, and added some inline comments here to call some things to your attention. Given that this is kind of a hidden feature for now and probably only used by EPS, it's probably good enough but will let you decide.
The main thing I want to hear back from you is about the case of variables with more than one dimension; the code seems to be set up to accept that case but there wasn't a test for this other than the small one I added so I want to make sure the way I tested it is how you expected it to work, or if there are other cases we should add. I'll wait for your feedback before I mark it approved.
| ]) | ||
| }) | ||
|
|
||
| it('should work for equations that are affected by separateAllVarsWithDims', () => { |
There was a problem hiding this comment.
We had an existing unit test (or something closer to a unit test) for specialSeparationDims and I think we should do the same for this new separateAllVarsWithDims so I added them. I always prefer to have vitest tests defined for things as the iteration cycle is much tighter than having to rely on sample model tests.
There was a problem hiding this comment.
These are better tests than the model test I added. I should start doing it that way. Shall we remove the model test, since the unit test covers the same thing?
The tests work the way I expected. I am thinking of separateAllVarsWithDims as a kind of shorthand for specialSeparationDims. They both have the effect of setting separationDims for the subscriptPositionsToExpand call, so the dim list has the same semantics.
There was a problem hiding this comment.
Shall we remove the model test, since the unit test covers the same thing?
No, I think there's value in having both kinds of tests. The model test helps verify things end-to-end (like, that the spec file is passed through the chain as expected).
| * name to separate on. | ||
| * separated because of circular references. This is an optional mapping from "C" variable name | ||
| * to "C" dimension name to separate on. | ||
| * @param {string[][]} [separateAllVarsWithDims] An optional array containing arrays of dimension |
There was a problem hiding this comment.
I changed the type to string[][] to make it slightly more obvious that how this works in the case of providing more than one dimension.
| if (dimList.every(dim => subIds.includes(dim))) { | ||
| // Technically we allow each entry in the spec array to be either a single | ||
| // dim ID string or an array of dim IDs | ||
| if (!Array.isArray(dimList)) { |
There was a problem hiding this comment.
I think it would be better to avoid having the implicit "up convert string to string[]" code so that you always have to provide a string[][] in the spec file, but I didn't make any changes to the code. I guess I'm fine leaving it as is given that this is basically a hidden feature.
There was a problem hiding this comment.
I was following the implementation we had for specialSeparationDims. I agree it would be safer to force the type, but in practice, it's nice to have the single string option.
| const parsedModel = { kind: 'vensim', root: parseVensimModel(eqnText) } | ||
|
|
||
| // Create one or more `Variable` instances from the equations | ||
| // TODO: Technically we should pass `spec.separateAllVarsWithDims` here so that any |
There was a problem hiding this comment.
I added a TODO here because it's possible that you could end up with generated vars that are not separated as expected. In practice I don't think this is likely to happen given that defineVariables is typically used in cases where the variables are already non-apply-to-all, but I could be wrong about that. Anyway, I think it's fine to not act on this now but wanted to flag it in case you think we should fix it now (it wouldn't be too hard to pass the spec to this function).
…ved prior to an earlier commit
chrispcampbell
left a comment
There was a problem hiding this comment.
Based on the discussion in the comments, I think this is fine to merge in its current state. As noted, I think there's value in having both kinds of tests, and no urgent changes needed in the code, so I will merge this now and publish a release.
Fixes #601
This PR proposes an alternative to the
specialSeparationDimssyntax to avoid having to maintain the list in cases where all variables containing a given subscript should be separated.The spec file can now contain a property named
separateAllVarsWithDimswith an array value. Each entry is either a dimension name string in canonical format, or an array of dimension names.If a variable LHS matches all dimension names in one of the
separateAllVarsWithDimsentries, then it is separated on those dimensions. If a variable is specifically called out inspecialSeparationDims, then that takes precedence, andseparateAllVarsWithDimsis not checked. It does not make sense for a variable separation to be listed in both formats.I added a test model called
separateall.mdlthat has two apply-to-all arrays namedaandb.Without a spec file, the following code and variable listing is generated.
I made a spec file that tests both separation methods:
The variables are separated in both cases:
Because generation and execution do not fail in this test model, I added a check script that generates the model listing and confirms that both variables are separated. This is the only way to test the PR, since we don't have a failing test otherwise.
I tested this change on an EPS 4 model and confirmed that the new spec file format results in the same C code generation as the previous spec file that listed each variable separately.