7aea80cb5c1d93db67bc2661da7b275bb998d030
[scilab.git] / scilab / modules / xcos / macros / xcos_simulate.sci
1 //
2 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 // Copyright (C) 2009-2009 - DIGITEO - Bruno JOFRET
4 //
5 // This file must be used under the terms of the CeCILL.
6 // This source file is licensed as described in the file COPYING, which
7 // you should have received as part of this distribution.  The terms
8 // are also available at
9 // http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10 //
11 //
12
13 function %cpr = xcos_simulate(scs_m, needcompile)
14
15 // Load the block libs if not defined
16   prot = funcprot();
17   funcprot(0);
18     if ~exists("scicos_diagram") then
19         loadXcosLibs();
20     end
21   funcprot(prot);
22   [modelica_libs, scicos_pal_libs, %scicos_with_grid, %scs_wgrid] = initial_scicos_tables();
23
24     // Hook according to SEP066
25     function [ok]=invoke_pre_simulate(fun, scs_m, needcompile)
26         ok=%f;
27         ierr=execstr('[continueSimulation]='+fun+'(scs_m, needcompile);', 'errcatch');
28         if ierr<>0 then
29             disp(_("Error occurred in pre_xcos_simulate: Cancelling simulation."));
30             [str,n,line,func]=lasterror();
31             mprintf(' at line %d of function %s\n', line, func);
32             return
33         end
34         if ~continueSimulation then
35             return
36         end
37         ok=%t;
38         
39         // force update on the parent in case of scoped modification
40         scs_m=resume(scs_m);
41     endfunction
42     
43   if isdef("pre_xcos_simulate") then
44       if type(pre_xcos_simulate) == 15 then
45           // if has a multiple implementation (on a list)
46           for f=pre_xcos_simulate;
47               ok=invoke_pre_simulate(f, scs_m, needcompile);
48               if ~ok then
49                   %cpr=[];
50                   return;
51               end
52           end
53       else
54           // if has a unique implementation
55           ok=invoke_pre_simulate("pre_xcos_simulate", scs_m, needcompile);
56           if ~ok then
57             %cpr=[];
58             return;
59           end
60       end
61   end
62
63   //**---- prepare from and to workspace stuff ( "From workspace" block )
64   scicos_workspace_init()
65
66
67 //** extract tolerances from scs_m.props.tol
68   tolerances = scs_m.props.tol ;
69   //** extract solver type from tolerances
70   solver = tolerances(6) ;
71   //** initialize a "scicos_debug_gr" variable
72   %scicos_debug_gr = %f;
73
74   ////////////////////////////////////////////////////////////////
75   // Add global environment variable so that scicos is not lost //
76   ////////////////////////////////////////////////////////////////
77   if needcompile == 4 then
78     %state0     = list();
79     needcompile = 4;
80     curwin      = 1000;
81     %cpr        = struct();
82     %tcur       = 0;
83     %cpr.state  = %state0;
84     alreadyran = %f;
85   else
86     %state0 = %cpr.state;
87     alreadyran = %f;
88   end
89
90   tf          = scs_m.props.tf;
91   %zoom       = 1.4;
92   Select      = [];
93
94   //** extract tolerances from scs_m.props.tol
95   tolerances = scs_m.props.tol ;
96   //** extract solver type from tolerances
97   solver = tolerances(6) ;
98
99   // Propagate context through all blocks
100   %scicos_context = struct();
101   context = scs_m.props.context;
102   //** context eval here
103   [%scicos_context, ierr] = script2var(context, %scicos_context);
104
105   //for backward compatibility for scifunc
106   if ierr==0 then
107     %mm = getfield(1,%scicos_context)
108     for %mi=%mm(3:$)
109       ierr = execstr(%mi+'=%scicos_context(%mi)','errcatch')
110       if ierr<>0 then
111         break; //** in case of error exit
112       end
113     end
114   end
115   //end of for backward compatibility for scifuncpagate context values
116
117   [scs_m,%cpr,needcompile,ok] = do_eval(scs_m, %cpr, %scicos_context);
118   if ~ok then
119       msg = msprintf(gettext("%s: Error during block parameters evaluation.\n"), "Xcos");
120       messagebox(msg, "Xcos", "error");
121       error(msprintf(gettext("%s: Error during block parameters evaluation.\n"), "xcos_simulate"));
122   end
123
124   //** update parameters or compilation results
125   [%cpr,%state0_n,needcompile,alreadyran,ok] = do_update(%cpr,%state0,needcompile)
126   if ~ok then
127     error(msprintf(gettext("%s: Error during block parameters update.\n"), "xcos_simulate"));
128   end
129
130   //** if alreadyran then set the var choice
131   if alreadyran then
132     choix = ['Continue';'Restart';'End']
133   else
134     choix = [] ;
135   end
136
137   issequal = %t;
138   //** initial state has been changed
139   if ~isequal(%state0_n,%state0) then
140     issequal = %f
141   else
142     //** test typeof outtb element
143     for i=1:lstsize(%state0_n.outtb)
144       if typeof(%state0_n.outtb(i))<>typeof(%state0.outtb(i))
145         issequal = %f
146         break
147       end
148     end
149     //** test typeof oz element
150     for i=1:lstsize(%state0_n.oz)
151       if typeof(%state0_n.oz(i))<>typeof(%state0.oz(i))
152         issequal = %f
153         break
154       end
155     end
156   end
157
158   //** if state have changed
159   //** finish the simulation via do_terminate()
160   if ~issequal then
161      %state0 = %state0_n
162     [alreadyran,%cpr] = do_terminate()
163     choix = []
164   end
165
166   //** switch appropriate solver
167   if %cpr.sim.xptr($)-1<size(%cpr.state.x,'*') & solver<100 then
168     warning(["Diagram has been compiled for implicit solver"
169              "switching to implicit Solver"])
170     solver = 100 ; //** Magic number
171     tolerances(6) = solver ; //** save Magic number solver type
172   elseif (%cpr.sim.xptr($)-1==size(%cpr.state.x,'*')) & (solver==100 & size(%cpr.state.x,'*')<>0) then
173     message(["Diagram has been compiled for explicit solver"
174              "switching to explicit Solver"])
175     solver = 0 ; //** Magic number
176     tolerances(6) = solver ; //** save Magic number solver type
177   end
178
179   //** ask user what to do
180   if choix<>[] then
181     //** open dialog box
182     to_do = choose(choix,"What do you want to do")
183
184     //** if cancel then exit
185     if to_do==0 then
186       ok = %f
187       return
188     end
189
190     select choix(to_do)
191
192       case "Continue" then
193         needstart = %f ;
194         state     = %cpr.state ;
195
196       case "Restart" then
197         needstart = %t ;
198         state     = %state0 ;
199
200       case "End" then
201         state     = %cpr.state ;
202         needstart = %t ;
203         tf        = scs_m.props.tf;
204
205         //Alan: Cannot call do_terminate() here ?
206         //Answer: No, because do_terminate() doesn't
207         //          return control to the user
208
209         //** run scicosim via 'finish' flag
210         ierr = execstr('[state,t]=scicosim(%cpr.state,%tcur,tf,%cpr.sim,'+..
211                        '''finish'',tolerances)','errcatch')
212
213         %cpr.state = state
214         alreadyran = %f
215
216         //** error case
217         if ierr<>0 then
218           str_err = split_lasterror(lasterror());
219           kfun    = curblock()
220           corinv  = %cpr.corinv
221
222           if kfun<>0 then //** block error
223             path = corinv(kfun)
224             //** get error cmd for the block
225             get_errorcmd(path,'End problem.',str_err);
226
227           else //** simulator error
228             message(["End problem:";str_err])
229             //scf(curwin);
230           end
231           ok = %f
232         end
233
234         return
235     end
236
237   else //** Normal first start simulation
238
239     needstart = %t
240     state     = %state0
241
242   end
243
244   //gh_win = gcf();
245
246   //** scicos initialization
247   if needstart then
248     //** if the simulation has already run
249     //** and is not finished then call do_terminate
250     if alreadyran then
251       [alreadyran,%cpr] = do_terminate()
252       alreadyran = %f ;
253     end
254     //** set initial values for a new simulation
255     %tcur      = 0
256     %cpr.state = %state0
257     tf         = scs_m.props.tf;
258     if tf*tolerances==[] then
259       message(["Simulation parameters not set";"use setup button"]);
260       return;
261     end
262
263     //** Run the normal first start simulation here
264
265     //** run scicosim via 'start' flag
266     ierr = execstr('[state,t]=scicosim(%cpr.state,%tcur,tf,%cpr.sim,'+..
267                    '''start'',tolerances)','errcatch')
268
269     %cpr.state = state ; //** save the state
270     //** error case
271     if ierr<>0 then
272       str_err=split_lasterror(lasterror());
273
274       kfun=curblock()
275       corinv=%cpr.corinv
276       if kfun<>0 then  //** block error
277         path=corinv(kfun)
278         //** get error cmd for the block
279         disp(str_err);
280         get_errorcmd(path,gettext('Initialisation problem'),str_err);
281
282
283       else //** simulator error
284         message(['Initialisation problem:';str_err])
285         //scf(curwin);
286       end
287
288       ok = %f;
289       //xset('window',curwin)
290       return
291     end
292     //scf(gh_win);
293     //xset('window',win);
294   end
295
296   //** scicos simulation
297   tf = scs_m.props.tf
298
299   // inform Xcos the simulator is going to run
300   xcosSimulationStarted();
301
302   //** run scicosim via 'start' flag
303   ierr = execstr('[state,t]=scicosim(%cpr.state,%tcur,tf,%cpr.sim,'+..
304                      '''run'',tolerances)','errcatch')
305
306   %cpr.state = state
307
308   //** no error
309   if ierr==0 then
310     alreadyran = %t;
311     //** we are at the end of the simulation
312     //** finish the simulation via do_terminate()
313     if tf-t<tolerances(3) then
314       //disp('fin');
315       //Alan : removing do_terminate() here because it
316       //       doesn't return control
317       //[alreadyran,%cpr]=do_terminate()
318       needstart  = %t;
319       alreadyran = %f;
320       //** run scicosim via 'finish' flag
321       ierr = execstr('[state,t]=scicosim(%cpr.state,tf,tf,%cpr.sim,'+..
322                      '''finish'',tolerances)','errcatch')
323
324       %cpr.state = state;
325
326       //** error case
327       if ierr<>0 then
328         str_err = split_lasterror(lasterror());
329
330         kfun   = curblock()
331         corinv = %cpr.corinv
332
333         if kfun<>0 then //** block error
334           path = corinv(kfun)
335           //** get error cmd for the block
336           get_errorcmd(path,gettext('End problem'),str_err);
337         else //** simulator error
338           message(['End problem:';str_err])
339           //scf(curwin);
340         end
341       end
342     else
343       %tcur = t;
344     end
345   //** error case
346   else
347     str_err = split_lasterror(lasterror());
348
349     alreadyran = %f;
350     kfun       = curblock();
351     corinv     = %cpr.corinv;
352
353     if kfun<>0 then //** block error
354       path = corinv(kfun);
355       //** get error cmd for the block
356       get_errorcmd(path,gettext("Simulation problem"),str_err);
357     else //** simulator error
358       message(['Simulation problem:';str_err])
359       //scf(curwin);
360     end
361     ok = %f;
362   end
363
364   //restore saved variables in Scilab environment ( "To workspace" block )
365   [txt,files]=returntoscilab()
366   n=size(files,1)
367   for i=1:n
368     load(TMPDIR+'/Workspace/'+files(i))
369     ierr = execstr(files(i)+'=struct('"values'",x,'"time'",t)', "errcatch")
370     if ierr <> 0
371        str_err = split_lasterror(lasterror());
372        message(['Simulation problem:';str_err]);
373     end
374
375   end
376
377     // Hook according to SEP066
378     function ok=invoke_post_simulate(fun, %cpr, scs_m, needcompile)
379         ok=%f;
380         ierr=execstr(fun+'(%cpr, scs_m, needcompile);', 'errcatch');
381         if ierr<>0 then
382             disp(_("Error in post_xcos_simulate: ending simulation."))
383             return
384         end
385         ok=%t
386         // force update on the parent in case of scoped modification
387         scs_m=resume(scs_m);
388     endfunction
389     
390     if isdef("post_xcos_simulate") then
391       if type(post_xcos_simulate) == 15 then
392           // if has a multiple implementation (on a list)
393           for f=post_xcos_simulate;
394               ok=invoke_post_simulate(f, scs_m, needcompile);
395               if ~ok then
396                   %cpr=[];
397                   return;
398               end
399           end
400       else
401           // if has a unique implementation
402           ok=invoke_post_simulate("post_xcos_simulate", %cpr, scs_m, needcompile);
403           if ~ok then
404             %cpr=[];
405             return;
406           end
407       end
408     end
409
410   // finally restore the exported variables on the parent context
411   if ~isempty(txt) then
412     ierr = execstr(txt, "errcatch")
413     if ierr <> 0 then
414         str_err = split_lasterror(lasterror());
415         message(['Simulation problem while executing <'+txt+'>:';str_err]);
416     end
417   end
418 endfunction
419