Xcos: add hooks pre/post simulation
[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
23     // Hook according to SEP066
24     if isdef("pre_xcos_simulate") then
25       try
26       continueSimulation = pre_xcos_simulate(scs_m, needcompile);
27       if ~continueSimulation then
28         %cpr = []
29         return
30       end
31       catch
32       disp(_("Error occured in pre_xcos_simulate: Cancelling simulation."))
33       %cpr = []
34       return
35       end
36     end
37
38   //**---- prepare from and to workspace stuff ( "From workspace" block )
39   xcos_workspace_init()
40
41
42 //** extract tolerances from scs_m.props.tol
43   tolerances = scs_m.props.tol ;
44   //** extract solver type from tolerances
45   solver = tolerances(6) ;
46   //** initialize a "scicos_debug_gr" variable
47   %scicos_debug_gr = %f;
48
49   ////////////////////////////////////////////////////////////////
50   // Add global environment variable so that scicos is not lost //
51   ////////////////////////////////////////////////////////////////
52   if needcompile == 4 then
53     %state0     = list();
54     needcompile = 4;
55     curwin      = 1000;
56     %cpr        = struct();
57     %tcur       = 0;
58     %cpr.state  = %state0;
59   else
60     %state0 = %cpr.state;
61     alreadyran = %f;
62   end
63
64   tf          = scs_m.props.tf;
65   %zoom       = 1.4;
66   Select      = [];
67
68   //** extract tolerances from scs_m.props.tol
69   tolerances = scs_m.props.tol ;
70   //** extract solver type from tolerances
71   solver = tolerances(6) ;
72
73   // Propagate context through all blocks
74   %scicos_context = struct();
75   context = scs_m.props.context;
76   //** context eval here
77   [%scicos_context, ierr] = script2var(context, %scicos_context);
78
79   //for backward compatibility for scifunc
80   if ierr==0 then
81     %mm = getfield(1,%scicos_context)
82     for %mi=%mm(3:$)
83       ierr = execstr(%mi+'=%scicos_context(%mi)','errcatch')
84       if ierr<>0 then
85         break; //** in case of error exit
86       end
87     end
88   end
89   //end of for backward compatibility for scifuncpagate context values
90
91   [scs_m,%cpr,needcompile,ok] = do_eval(scs_m, %cpr, %scicos_context);
92   if ~ok then
93     error(msprintf(gettext("%s: Error during block parameters evaluation.\n"), "xcos_simulate"));
94   end
95
96   //** update parameters or compilation results
97   [%cpr,%state0_n,needcompile,alreadyran,ok] = do_update(%cpr,%state0,needcompile)
98   if ~ok then
99     error(msprintf(gettext("%s: Error during block parameters update.\n"), "xcos_simulate"));
100   end
101
102   //** if alreadyran then set the var choice
103   if alreadyran then
104     choix = ['Continue';'Restart';'End']
105   else
106     choix = [] ;
107   end
108
109   issequal = %t;
110   //** initial state has been changed
111   if ~isequal(%state0_n,%state0) then
112     issequal = %f
113   else
114     //** test typeof outtb element
115     for i=1:lstsize(%state0_n.outtb)
116       if typeof(%state0_n.outtb(i))<>typeof(%state0.outtb(i))
117         issequal = %f
118         break
119       end
120     end
121     //** test typeof oz element
122     for i=1:lstsize(%state0_n.oz)
123       if typeof(%state0_n.oz(i))<>typeof(%state0.oz(i))
124         issequal = %f
125         break
126       end
127     end
128   end
129
130   //** if state have changed
131   //** finish the simulation via do_terminate()
132   if ~issequal then
133      %state0 = %state0_n
134     [alreadyran,%cpr] = do_terminate()
135     choix = []
136   end
137
138   //** switch appropriate solver
139   if %cpr.sim.xptr($)-1<size(%cpr.state.x,'*') & solver<100 then
140     message(["Diagram has been compiled for implicit solver"
141              "switching to implicit Solver"])
142     solver = 100 ; //** Magic number
143     tolerances(6) = solver ; //** save Magic number solver type
144   elseif (%cpr.sim.xptr($)-1==size(%cpr.state.x,'*')) & (solver==100 & size(%cpr.state.x,'*')<>0) then
145     message(["Diagram has been compiled for explicit solver"
146              "switching to explicit Solver"])
147     solver = 0 ; //** Magic number
148     tolerances(6) = solver ; //** save Magic number solver type
149   end
150
151   //** ask user what to do
152   if choix<>[] then
153     //** open dialog box
154     to_do = choose(choix,"What do you want to do")
155
156     //** if cancel then exit
157     if to_do==0 then
158       ok = %f
159       return
160     end
161
162     select choix(to_do)
163
164       case "Continue" then
165         needstart = %f ;
166         state     = %cpr.state ;
167
168       case "Restart" then
169         needstart = %t ;
170         state     = %state0 ;
171
172       case "End" then
173         state     = %cpr.state ;
174         needstart = %t ;
175         tf        = scs_m.props.tf;
176
177         //Alan: ONPEUTPASAPPELLERDOTERMINATEICI?
178         //reponse : non, car do_terminate() ne rend
179         //          pas forc�ment la main � l'utilisateur
180
181         //** run scicosim via 'finish' flag
182         ierr = execstr('[state,t]=scicosim(%cpr.state,%tcur,tf,%cpr.sim,'+..
183                        '''finish'',tolerances)','errcatch')
184
185         %cpr.state = state
186         alreadyran = %f
187
188         //** error case
189         if ierr<>0 then
190           str_err = split_lasterror(lasterror());
191           kfun    = curblock()
192           corinv  = %cpr.corinv
193
194           if kfun<>0 then //** block error
195             path = corinv(kfun)
196             //** get error cmd for the block
197             get_errorcmd(path,'End problem.',str_err);
198
199           else //** simulator error
200             message(["End problem:";str_err])
201             //scf(curwin);
202           end
203           ok = %f
204         end
205
206         return
207     end
208
209   else //** Normal first start simulation
210
211     needstart = %t
212     state     = %state0
213
214   end
215
216   //gh_win = gcf();
217
218   //** scicos initialisation
219   if needstart then
220     //** if the simulation have already ran
221     //** and is not finished then call do_terminate
222     if alreadyran then
223       [alreadyran,%cpr] = do_terminate()
224       alreadyran = %f ;
225     end
226     //** set initial values for a new simulation
227     %tcur      = 0
228     %cpr.state = %state0
229     tf         = scs_m.props.tf;
230     if tf*tolerances==[] then
231       message(["Simulation parameters not set";"use setup button"]);
232       return;
233     end
234
235     //** Run the normal first start simulation here
236
237     //** run scicosim via 'start' flag
238     ierr = execstr('[state,t]=scicosim(%cpr.state,%tcur,tf,%cpr.sim,'+..
239                    '''start'',tolerances)','errcatch')
240
241     %cpr.state = state ; //** save the state
242     //** error case
243     if ierr<>0 then
244       str_err=split_lasterror(lasterror());
245
246       kfun=curblock()
247       corinv=%cpr.corinv
248       if kfun<>0 then  //** block error
249         path=corinv(kfun)
250         //** get error cmd for the block
251         disp(str_err);
252         get_errorcmd(path,gettext('Initialisation problem'),str_err);
253
254
255       else //** simulator error
256         message(['Initialisation problem:';str_err])
257         //scf(curwin);
258       end
259
260       ok = %f;
261       //xset('window',curwin)
262       return
263     end
264     //scf(gh_win);
265     //xset('window',win);
266   end
267
268   //** scicos simulation
269   //needreplay=%t
270   tf = scs_m.props.tf;
271   //setmenu(curwin,'Stop')
272   //timer()
273   needreplay = %t
274
275   //** run scicosim via 'start' flag
276   ierr = execstr('[state,t]=scicosim(%cpr.state,%tcur,tf,%cpr.sim,'+..
277                      '''run'',tolerances)','errcatch')
278
279   %cpr.state = state
280
281   //** no error
282   if ierr==0 then
283     alreadyran = %t;
284     //** we are at the end of the simulation
285     //** finish the simulation via do_terminate()
286     if tf-t<tolerances(3) then
287       //disp('fin');
288       //Alan : j'enl�ve do_terminate ici car do_terminate
289       //       ne rend pas la main
290       //[alreadyran,%cpr]=do_terminate()
291       needstart  = %t;
292       alreadyran = %f;
293       //** run scicosim via 'finish' flag
294       ierr = execstr('[state,t]=scicosim(%cpr.state,tf,tf,%cpr.sim,'+..
295                      '''finish'',tolerances)','errcatch')
296
297       %cpr.state = state;
298
299       //** error case
300       if ierr<>0 then
301         str_err = split_lasterror(lasterror());
302
303         kfun   = curblock()
304         corinv = %cpr.corinv
305
306         if kfun<>0 then //** block error
307           path = corinv(kfun)
308           //** get error cmd for the block
309           get_errorcmd(path,gettext('End problem'),str_err);
310         else //** simulator error
311           message(['End problem:';str_err])
312           //scf(curwin);
313         end
314       end
315     else
316       %tcur = t;
317     end
318   //** error case
319   else
320     str_err = split_lasterror(lasterror());
321
322     alreadyran = %f;
323     kfun       = curblock();
324     corinv     = %cpr.corinv;
325
326     if kfun<>0 then //** block error
327       path = corinv(kfun);
328       //** get error cmd for the block
329       get_errorcmd(path,gettext("Simulation problem"),str_err);
330     else //** simulateur error
331       message(['Simulation problem:';str_err])
332       //scf(curwin);
333     end
334     ok = %f;
335   end
336
337   //restore saved variables in Scilab environment ( "To workspace" block )
338   [txt,files]=returntoscilab()
339   n=size(files,1)
340   for i=1:n
341     load(TMPDIR+'/Workspace/'+files(i))
342     execstr(files(i)+'=struct('"values'",x,'"time'",t)')
343   end
344   execstr(txt)
345
346     // Hook according to SEP066
347     if isdef("post_xcos_simulate") then
348       try
349       post_xcos_simulate(%cpr, scs_m, needcompile);
350       catch
351       disp(_("Error in post_xcos_simulate: ending simulation."))
352       end
353     end
354
355   needreplay = resume(needreplay);
356 endfunction
357