Initializing Levels from a Delphi application

Use this forum to post Vensim related questions.
Post Reply
PeterB
Junior Member
Posts: 11
Joined: Fri Apr 04, 2008 1:28 pm

Initializing Levels from a Delphi application

Post by PeterB »

Dear colleagues,

I wrote a Delphi 5.0 application which controls a small Vensim model. Everything (starting, stopping simulations, getting data from the model during and after simulation) is fine, except that I don't manage to override the initial values of the levels from the application.


Some lines of Delphi code to illustrate my problem:


// Declaration in the units' 'implementation' part

function vensim_command(command_string: PChar): Integer ; stdcall ; external 'vendll32.dll' ;


// Global variable, contains the initial values for the levels.

var InitSubstrate: array[1..20,1..20] of Single;


// This procedure is called after the model is loaded successfully
// and before simulation starts.
// Substrate Height[x1..x20, y1..y20] is a matrix of levels in the
// Vensim Model.

procedure InitializeLevels;

var result, x, y: Integer;
Text: PChar;

begin

for x := 1 to 20 do for y := 1 to 20 do begin

Text := PChar('"SIMULATE>SETVAL|initial Substrate Height[x' + IntToStr(x) + ',y' + IntToStr(y) + '] = ' + FloatToStr(InitSubstrate[x,y]) + '"');

result := vensim_command(Text);

end; // for x, y

end; // procedure


While vensim_command always returns 1 indicating successful execution of Text (which itself looks reasonable to me), the initial values provided with InitSubstrate don't seem to arrive at the model. Instead, it keeps using the original initial values I used when building the model in Vensim. Does anyone out there see what I'm doing wrong?

Greetings
Peter
Administrator
Super Administrator
Posts: 4590
Joined: Wed Mar 05, 2003 3:10 am

Post by Administrator »

You are executing the correct command.

Do you load a CIN file before starting the simulation?

Tony.
bob@vensim.com
Senior Member
Posts: 1107
Joined: Wed Mar 12, 2003 2:46 pm

Post by bob@vensim.com »

Assuming that initial Substrate Height[x,y] is the initial value for the level in the model this looks like it should work. This should be the last thing called before starting the simulation with either MENU>RUN or vensim_start_simulation. My best guess is you are doing something else that causes these values to be discarded.
PeterB
Junior Member
Posts: 11
Joined: Fri Apr 04, 2008 1:28 pm

Post by PeterB »

Hi Tony, hi Bob,

thanks for your quick replies! In the meantime, I took some effort to check and reorganize everything (which improved my application quite a bit), but the problem persists. I don't load any CIN-file and I'm sure now that nothing happens between level initialization and simulation start.

I think, again, a piece of Delphi code will show best what I mean:


procedure TTestForm.SimulateBetterButtonClick(Sender: TObject);
// Simulate the model and fetch the level values during
// and after simulation.

var result, index: Integer;
Text, RunName: PChar;

begin
RunName := 'Current';
Text := PChar('SIMULATE>RUNNAME|' + RunName);
result := vensim_command(Text);

InitializeLevels; // Pretends to work, but initial values don't seem to arrive at the Vensim model.

result := vensim_start_simulation(1,0,1);

if result = 1 then begin
while result = 1 do begin
GetLevels_during_Simulation(RunName, index); // Uses vensim_get_val. Works.
Update_Diagrams(index);
result := vensim_continue_simulation(5);
end; // while

result := vensim_finish_simulation;

GetLevels_after_Simulation(RunName); // Uses vensim_get_data. Works.

// Show something to the user.
Update_Diagrams(400);
SpinEdit1.Value := 50;

end; // if result = 1;


end; //procedure TTestForm.SimulateBetterButtonClick;



The procedure InitializeLevels which is called here is the same as shown in my post above. What I didn't show there, was that the initial values I want to pass to Vensim are loaded from a textfile (this works) before going into the loop where setval is called.

The setval commands pretend to work, but when I look at the actual initial values of the levels as obtained via vensim_get_val or vensim_get_data they seem to have had no effect. The Vensim model itself does its job perfectly.

The model is loaded immediately after launching the application. It's a vpm-file.

Do you have an idea what I could try to locate the problem?

Greetings
Peter
bob@vensim.com
Senior Member
Posts: 1107
Joined: Wed Mar 12, 2003 2:46 pm

Post by bob@vensim.com »

Hi Peter,

I can't see anything obviously wrong. The best way to get to the bottom of this is probably to create a separate Delphi program that loads a trivial model (eg population=INTEG( births-deaths,100)) set a nonsubscripted variable (eg SIMULATE>SETVAL|birthrate=0.08) then simulates. If that works add a subscript. If that works try your model in the trivial program. If that works try the trivial model with your program. Hopefully one of these steps will offer insight.
PeterB
Junior Member
Posts: 11
Joined: Fri Apr 04, 2008 1:28 pm

Post by PeterB »

Hi Bob,

may I bother you again? I'm not sure, but maybe there is a communication problem between VensimDLL and Delphi.

Following your suggestion, I created a trivial Vensim model (Water Reservoir with constant inflow and Level-proportional outflow):


Outflow Rate=
0.01
~ 1/Second
~ |

Outflow=
Outflow Rate*Water
~ m*m*m/Second
~ |

Inflow=
10
~ m*m*m/Second
~ |

Water= INTEG (
Inflow-Outflow,
100)
~ m*m*m
~ |



Then, I wrote a trivial Delphi program (comprising three procedures):

//------------------------------------------------------------------------------
procedure TTestForm.FormCreate(Sender: TObject);
// Called once, after application is launched.
var result: Integer;
begin
Randomize;
result := vensim_command('SPECIAL>LOADMODEL|Water.vpm');
result := vensim_command('SPECIAL>READCUSTOM|WaterGraph.vgf') ;
end;

//------------------------------------------------------------------------------
procedure InitializeLevel;
// Procedure for testing different attempts to initialize the level.
var result: Integer;
Rand: Single;
Text: PChar;
begin
Rand := 5000 * random;
Text := PChar('"SIMULATE>SETVAL|INITIAL Water = ' + FloatToStr(Rand) + '"'); // pretends to work
// Text := PChar('"SIMULATE>SETVAL|INITIAL Water = ' + FloatToStr(Rand)); // pretends to work
// Text := PChar('"SIMULATE>SETVAL|Water INITIAL = ' + FloatToStr(Rand) + '"'); // pretends to work
// Text := PChar('"SIMULATE>SETVAL|Water INIT = ' + FloatToStr(Rand) + '"'); // Even this pretends to work

// Text := PChar('SIMULATE>SETVAL|INITIAL Water = ' + FloatToStr(Rand)); // Doesn't pretend to work, seemingly, because double quotes are missing. But shouldn't those be necessary for subscripted variables only?

// Text := PChar('"SIMULATE>SETVAL|Outflow Rate = 0.05"'); // pretends to work

result := vensim_command(Text);
end;

//------------------------------------------------------------------------------
procedure TTestForm.SimulateButton1Click(Sender: TObject);
// Called, when user wants to run the model.
var result: Integer;
Time, Water: array[0..2000] of Single;

begin
result := vensim_command('SIMULATE>RUNNAME|Current');
InitializeLevel;
result := vensim_command('MENU>RUN|O');

// Values from vensim_get_data and the custom graph match
result := vensim_get_data('Current', 'Water', 'Time', @Water[0], @Time[0], 2001);
result := vensim_tool_command('CUSTOM>WaterLevel', ChartPanel1.Handle, 0);
end;

//------------------------------------------------------------------------------


The problem already arose at the first step: Nearly all variations of SETVAL commands I tried (see out-commented lines in InitializeLevel) pretended to work (result = 1) except the one without double quotes ("), but the Vensim Model seems to ignore them. It keeps simulating, but stubbornly sticks to the 'builtin' initial value of 100 m³. I also can't change the value of the constant 'Outflow Rate' with SETVAL.

Could it be some country specific system settings (Germany, in my case)? I tried some changes in Windows' number format (decimal separator, etc.) but without effect so far.


Looking for a workaround:
In order to make the other (non-trivial) application work, I'm thinking about making the program write the desired initial values for the levels into a text file which is then taken by vensim in order to initialize the levels from there. Is that possible?

Greetings
Peter
Administrator
Super Administrator
Posts: 4590
Joined: Wed Mar 05, 2003 3:10 am

Post by Administrator »

Is that the exact model you are loading into your Delphi app?

It will not work at present as the equation for "water" has no initial constant.

You would need to change the equation for "Water" from
Water= INTEG (Inflow-Outflow,100)
to
Water= INTEG ( Inflow - Outflow , INITIAL WATER )

Can you try making that modification to the model. Then try the following command and see if it changes the value for INITIAL WATER.
Text := PChar('SIMULATE>SETVAL|INITIAL WATER=200');

Tony.
PeterB
Junior Member
Posts: 11
Joined: Fri Apr 04, 2008 1:28 pm

Post by PeterB »

Hi Tony,

many thanks for clarification. Now it works. Actually, I thought, INITIAL would be part of the command when a level is to be initialized.

What confused me when testing was that vensim_command() seems to always return 1 when the command starts with ".

Greetings
Peter
Post Reply