Page 1 of 1
external function / constant matrices
Posted: Mon Nov 15, 2010 7:28 am
by etam
Hi,
Another question about external functions.
You can define a constant with an external function, which is great.
You can get any variable's subscripts with *VENGV->get_varattrib, fine.
But can I get the fix subscripts from a definition?
I mean:
In your example you use:
constant[area,climate] = MYCONSTDEF('string')
However, these are also valid definitions:
sub : element1, element2 ~~|
constant2[area, climate, element1] = MYCONSTDEF('string') ~~|
constant3[area, element2, climate] = MYCONSTDEF('string') ~~|
Can I somehow get which subscripts varying in constant2 and constant3 above?
I couldn't find any solution in the docs and in your codes, so I reckon I can't, but it's better to ask it...
Posted: Mon Nov 15, 2010 10:01 am
by Administrator
If you mark the function down has having user managed loops (in this example, it would have to be 2), you can work out what subscript elements you are dealing with.
Posted: Mon Nov 15, 2010 10:24 am
by bob@vensim.com
the CONSTANT_MATRIX structure has in it the number of rows and columns requested. If you look at the example you will see how these are filled in. You can only have 2 subscripts varying so use the 'string' to specify which block of numbers is being requested. This is actually the same as the way GET XLS CONSTANTS works.
Posted: Mon Nov 15, 2010 11:01 am
by etam
Thanks Bob.
I thought that, but was hoping there is a nicer solution.
Posted: Mon Nov 15, 2010 3:27 pm
by tomfid
Why do you want to do this? If you specify the problem you're trying to solve, you might get more useful answers.
Tom
Posted: Tue Nov 16, 2010 9:45 am
by etam
I've created a general GAMS-Vensim interface.
One of its component reads data from GDX files (which are similar to VDF files).
This component has a function, something like this:
ReadFromGDX(CONSTANT_MATRIX *cmat, char *GDXFileName);
It gets the subscripts of cmat as interface-dictionary and uses them to read data from the GDX, which means that both Vensim and GAMS must have similar structures.
Let's assume the GDX has values of a variable:
Elasticities(Sectors, TimeShifts)
In my Vensim model there are two contants:
ELASTICITY GENERAL(SECTORS, TIMESHIFTS)
ELASTICITY SPEC(REGIONS, SECTORS, TIMESHIFTS)
(countries, sectors and timeshifts are subscript ranges)
For some reason I want to use them as follows:
ELASTICITY GENERAL(SECTORS, TIMESHIFTS) = ReadFromGDX('general.gdx') ~~|
ELASTICITY GENERAL(AFRICA, SECTORS, TIMESHIFTS) = ReadFromGDX('africa.gdx') ~~|
ELASTICITY GENERAL(AMERICA, SECTORS, TIMESHIFTS) = ReadFromGDX('america.gdx') ~~|
...
Unfortunately I can write it only that way:
ELASTICITY GENERAL(SECTORS, TIMESHIFTS) = ReadFromGDX('general.gdx', '') ~~|
ELASTICITY GENERAL(AFRICA, SECTORS, TIMESHIFTS) = ReadFromGDX('africa.gdx', 'AFRICA') ~~|
ELASTICITY GENERAL(AMERICA, SECTORS, TIMESHIFTS) = ReadFromGDX('america.gdx','AMERICA') ~~|
...
That's my simplest problem, but as you can read in the first post, also ordering matters.
Anyway, as Bob answered, there is no other solution.
Btw, thanks for the quick replies, it's really amazing!
Posted: Tue Nov 16, 2010 11:15 pm
by tomfid
Cool. Unfortunately I don't have any further helpful suggestion.
Just to indulge my curiousity though ... is your Vensim model calling/running a live GAMS model at each iteration, or using the GAMS results as a kind of fixed library of inputs, or ... ?
Tom
Posted: Wed Nov 17, 2010 8:25 am
by etam
It's a general library, both are possible.
We have good results, it is fast enough. Now we are working on making it more general (that's why I asked my questions).
Posted: Wed Nov 17, 2010 8:37 am
by etam
Btw, with vensim_get_varattrib I can get the equations:
constant2[area, climate, element1] = MYCONSTDEF('string')
constant3[area, element2, climate] = MYCONSTDEF('string')
Isn't there any function which could tell me which is currently used if vensim_external is called?
Or any undocumented feature or tag?
Posted: Wed Nov 17, 2010 12:47 pm
by bob@vensim.com
If you call vensim_get_varoff you can find the offset in the computational vector (VENGV->LEVEL) and you can compare this with the address passed by a self looping function to determine what variable is being computed. You can probably get this to work, but it will take some experimentation and effort.
Posted: Wed Nov 17, 2010 5:52 pm
by etam
Uhh, I'm afraid I can't follow you this time.
Based on constmat/datamat->varname I know what variable is being computed.
And for user loops I know what subscripts are skipped.
I have problems only with constant and data definitions.
But offset won't work for them, since they have different storage in the CONSTANT_MATRIX, DATA_MATRIX structure, haven't they?
Moreover, VENGV->get_varoff(val[0].constmat->varname) returns 0 for me (within func vensim_external). Does it need any special initialization which is not mentioned in the doc?
Anyway, it's not really important, it can be solved with the literals.
Thanks for suggestions!