bug 4715 fix
[scilab.git] / scilab / modules / scicos / macros / scicos_auto / scicos_simulate.sci
1 //  Scicos
2 //
3 //  Copyright (C) INRIA - METALAU Project <scicos@inria.fr>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 // See the file ./license.txt
20 //
21
22 function Info = scicos_simulate(scs_m, Info, %scicos_context, flag, Ignb)
23 // Function for running scicos simulation in batch mode
24 // Info = scicos_simulate(scs_m[,Info][,%scicos_context][,flag][,Ignb])
25 //
26 // scs_m: scicos diagram (obtained by "load file.cos"). Note that
27 // the version of file.cos must be the current version. If not, load
28 // into scicos and save.
29 //
30 // %scicos_context: a scilab struct containing values of
31 // symbolic variables used in the context and Scicos blocks. This
32 // is often used to change a parameter in the diagram context. In that
33 // case, make sure that in the diagram context the variable is defined such
34 // that it can be modified. Say a variable "a" is to be defined in the
35 // context having value 1, and later in batch mode, we want to change
36 // the value of "a". In that case, in the context of the diagram place:
37 //  if ~exists('a') then a=1,end
38 // If you want then to run the simulation in batch mode using the value
39 // a=2, set:
40 // %scicos_context.a=2
41 //
42 // Info: a list. It must be list() at the first call, then use output
43 // Info as input Info for the next calls. Info contains compilation and
44 // simulation information and is used to avoid recompilation when not
45 // needed.
46 //
47 // flag: string. If it equals 'nw' (no window), then blocks using
48 // graphical windows are not executed. Note that the list of such
49 // blocks must be updated as new blocks are added.
50 //
51 // Ignb : matrix of string : The name of blocks to ignore.
52 // If flag is set and equal to 'nw' then Ignb contains
53 // name of blocks that are added to the list
54 // of blocks to ignore.
55 //
56
57   noguimode = find(sciargs() == "-nogui");
58   if (noguimode <> []) then
59      clear noguimode
60      flag = 'nw'
61   //    warning(" Scilab in no gui mode : Scicos unavailable");
62   //    abort;
63   end
64   clear noguimode
65
66   //** define Scicos data tables
67   if (~isdef("scicos_pal") | ~isdef("%scicos_menu") | ..
68       ~isdef("%scicos_short") | ~isdef("%scicos_help") | ..
69       ~isdef("%scicos_display_mode") | ~isdef("modelica_libs") | ..
70       ~isdef("scicos_pal_libs") | ~isdef("%scicos_gif") | ..
71       ~isdef("%scicos_contrib") ) then
72          [scicos_pal, %scicos_menu,...
73           %scicos_short, %scicos_help,..
74           %scicos_display_mode, modelica_libs,..
75           scicos_pal_libs, %scicos_gif,..
76           %scicos_contrib] = initial_scicos_tables()
77          clear initial_scicos_tables
78   end
79
80   //** initialize a "scicos_debug_gr" variable
81   %scicos_debug_gr = %f;
82
83   //** list of scopes to ignore
84   Ignoreb = ['bouncexy', ...
85              'cscope', ...
86              'cmscope', ...
87              'canimxy', ...
88              'canimxy3d', ...
89              'cevscpe', ...
90              'cfscope', ...
91              'cscopxy', ...
92              'cscopxy3d', ...
93              'cmatview', ...
94              'cmat3d', ...
95              'affich', ...
96              'affich2']
97
98   //** load macros libraries and palettes
99   // Scilab 5 new modules split
100   load('SCI/modules/scicos/macros/scicos_auto/lib')
101   load('SCI/modules/scicos/macros/scicos_utils/lib')
102   load('SCI/modules/scicos/macros/scicos_scicos/lib')
103
104   exec(loadpallibs,-1)
105
106   //** redefine some gui functions
107   prot = funcprot();funcprot(0);
108   deff('disablemenus()',' ')
109   deff('enablemenus()',' ')
110   do_terminate = do_terminate1
111   funcprot(prot)
112
113   //** check/set rhs parameters
114   if argn(2) == 1 then
115     Info            = list()
116     %scicos_context = struct()
117     flag            = []
118     Ignb            = []
119
120   elseif argn(2) == 2 then
121     if type(Info) == 10 & (stripblanks(Info) == 'nw') then
122       Info = list()
123       flag = 'nw'
124     elseif type(Info) <> 15 then
125       Info = list()
126       flag = []
127     else
128       flag = []
129     end
130     %scicos_context = struct()
131     Ignb = []
132
133         elseif argn(2) == 3 then
134     if type(Info) <> 15 then
135       Info = list()
136     end
137     if type(%scicos_context) == 10 & (stripblanks(%scicos_context) == 'nw') then
138       %scicos_context = struct()
139       flag = 'nw'
140     elseif type(%scicos_context) <> 17 then
141       %scicos_context = struct()
142       flag = []
143     else
144       flag = []
145     end
146     Ignb = []
147
148   elseif argn(2) == 4 then
149     if type(Info) <> 15 then
150       Info = list()
151     end
152     if type(%scicos_context) <> 17 then
153       %scicos_context = struct()
154     end
155     if type(flag) <> 10 then
156      flag = []
157     elseif (stripblanks(flag) <> 'nw') then
158        flag = []
159     end
160     Ignb = []
161
162   elseif argn(2) == 5 then
163     if type(Info) <> 15 then
164       Info = list()
165     end
166     if type(%scicos_context) <> 17 then
167       %scicos_context = struct()
168     end
169     if type(flag) <> 10 then
170       flag = []
171     elseif (stripblanks(flag) <> 'nw') then
172       flag = []
173     end
174     if type(Ignb) <> 10 then
175       Ignb = []
176     else
177       Ignb = (Ignb(:))'
178     end
179
180   else
181     error(mprintf(gettext("%s: Wrong number of input arguments. Must be between %d and %d.\n"), "scicos_simulate", 1, 5))
182   end
183   
184   //check version
185   current_version = get_scicos_version()
186   scicos_ver = find_scicos_version(scs_m)
187
188   //do version
189   if scicos_ver <> current_version then
190     ierr = execstr('scs_m = do_version(scs_m, scicos_ver)','errcatch')
191     if ierr <> 0 then
192       message("Can''t convert old diagram (problem in version)")
193       return
194     end
195   end
196
197   //prepare from and to workspace stuff
198   curdir = getcwd()
199   chdir(TMPDIR)
200   mkdir('Workspace')
201   chdir('Workspace')
202   %a = who('get');
203   %a = %a(1:$-predef()+1);  // exclude protected variables
204   for %ij = 1:size(%a,1)
205     var = %a(%ij)
206     if var <> 'ans' & typeof(evstr(var)) == 'st' then
207       ierr = execstr('x = ' + var + '.values','errcatch')
208       if ierr == 0 then
209         ierr = execstr('t = ' + var + '.time','errcatch')
210       end
211       if ierr == 0 then
212         execstr('save('"' + var + ''",x,t)')
213       end
214     end
215   end
216   chdir(curdir)
217   // end of /prepare from and to workspace stuff
218
219   Ignore = []
220
221   if flag == 'nw' then
222     Ignore = Ignoreb
223   end
224
225   if Ignb <> [] then
226     Ignore = [Ignore, Ignb]
227   end
228
229   //** retrieve Info list
230   if Info <> list() then
231     [%tcur, %cpr, alreadyran, needstart, needcompile, %state0] = Info(:)
232   else
233     %tcur = 0;
234     %cpr = list();
235     alreadyran = %f;
236     needstart = %t;
237     needcompile = 4;
238     %state0 = list();
239   end
240
241   //** set solver
242   tolerances     = scs_m.props.tol
243   solver         = tolerances(6)
244   %scicos_solver = solver
245
246   //** set variables of context
247   [%scicos_context, ierr] = script2var(scs_m.props.context, ...
248                 %scicos_context);
249   if ierr == 0 then //++ no error
250
251     [scs_m, %cpr, needcompile, ok] = do_eval(scs_m, %cpr)
252     if ~ok then 
253        error(['Error during block parameters evaluation , ' + lasterror()])
254     end
255     if needcompile <> 4 & size(%cpr) > 0 then
256       %state0 = %cpr.state
257     end
258     alreadyran = %f
259   else
260     error(['Incorrect context definition, ' + lasterror()])
261   end
262
263   if %cpr == list() then
264     need_suppress  =%t
265   else
266     need_suppress = %f
267   end
268
269   [%cpr, %state0_n, needcompile, alreadyran, ok] = do_update(%cpr, ...
270                 %state0, needcompile)   
271   
272   if ~ok then
273     error('Error updating parameters.')
274   end
275
276   if or(%state0_n <> %state0) then //initial state has been changed
277     %state0 = %state0_n
278     [alreadyran, %cpr] = do_terminate1(scs_m, %cpr)
279     choix = []
280   end
281   if (%cpr.sim.xptr($) - 1) < size(%cpr.state.x,'*') & solver < 100 then
282     warning(['Diagram has been compiled for implicit solver'
283              'switching to implicit solver'])
284     solver = 100
285     tolerances(6) = solver
286   elseif (%cpr.sim.xptr($) - 1) == size(%cpr.state.x,'*') & ...
287                 solver == 100 & size(%cpr.state.x,'*') <> 0 then
288     warning(['Diagram has been compiled for explicit solver'
289              'switching to explicit solver'])
290     solver = 0
291     tolerances(6) = solver
292   end
293
294   if need_suppress then //this is done only once
295     for i = 1:length(%cpr.sim.funs)
296       if type(%cpr.sim.funs(i)) <> 13 then
297         if find(%cpr.sim.funs(i)(1) == Ignore) <> [] then
298           %cpr.sim.funs(i)(1) = 'trash';
299         end
300       end
301     end
302   end
303
304   if needstart then //scicos initialisation
305     if alreadyran then
306       [alreadyran, %cpr] = do_terminate1(scs_m, %cpr)
307       alreadyran = %f
308     end
309     %tcur = 0
310     %cpr.state = %state0
311     tf = scs_m.props.tf;
312     if tf*tolerances == [] then
313       error(['Simulation parameters not set']);
314     end
315     ierr = execstr('[state, t] = scicosim(%cpr.state, %tcur, tf, %cpr.sim,' + ..
316                  '''start'', tolerances)','errcatch')
317     if ierr <> 0 then
318       error(['Initialisation problem:'])
319     end
320     %cpr.state = state
321   end
322
323   ierr = execstr('[state, t] = scicosim(%cpr.state, %tcur, tf, %cpr.sim,' + ..
324                 '''run'', tolerances)','errcatch')
325   if ierr == 0 then
326     %cpr.state = state
327     alreadyran = %t
328     if (tf - t) < tolerances(3) then
329       needstart = %t
330       [alreadyran, %cpr] = do_terminate1(scs_m, %cpr)
331     else
332       %tcur = t
333     end
334   else
335     error(['Simulation problem: ';lasterror()])
336   end
337
338   Info = list(%tcur, %cpr, alreadyran, needstart, needcompile, %state0)
339
340   [txt, files] = returntoscilab()
341   n = size(files,1)
342   for i = 1:n
343     load(TMPDIR + '/Workspace/' + files(i))
344     execstr(files(i) + ' = struct('"values'", x, '"time'", t)')
345   end
346   execstr(txt)
347 endfunction
348
349 function [alreadyran, %cpr] = do_terminate1(scs_m, %cpr)
350 // Copyright INRIA
351
352   if prod(size(%cpr)) < 2 then
353                 alreadyran = %f
354                 return
355         end
356
357         par = scs_m.props;
358
359   if alreadyran then
360     alreadyran = %f
361     // terminate current simulation
362     ierr = execstr('[state, t] = scicosim(%cpr.state, par.tf, par.tf, %cpr.sim, ''finish'', par.tol)', 'errcatch')
363
364     %cpr.state = state
365     if ierr <> 0 then
366       error(['End problem: ' ; lasterror()])
367     end
368   end
369 endfunction