1 |
REQUIRE "atoms.a4l"; |
2 |
(* => atoms.a4l, measures.a4l, system.a4l, basemodel.a4l *) |
3 |
PROVIDE "bvp.a4l"; |
4 |
|
5 |
(* |
6 |
* bvp.a4l |
7 |
* by Benjamin A Allan |
8 |
* remodeled from integration.a4l |
9 |
* by Peter Piela, Boyd T. Safrit, Joseph J. Zaher |
10 |
* Part of the ASCEND Library |
11 |
* $Date: 1998/06/17 18:49:40 $ |
12 |
* $Revision: 1.6 $ |
13 |
* $Author: mthomas $ |
14 |
* $Source: /afs/cs.cmu.edu/project/ascend/Repository/models/bvp.a4l,v $ |
15 |
* |
16 |
* This file is part of the ASCEND Modeling Library. |
17 |
* |
18 |
* Copyright (C) 1997 Benjamin A Allan |
19 |
* Copyright (C) 1998 Carnegie Mellon University |
20 |
* |
21 |
* The ASCEND Modeling Library is free software; you can redistribute |
22 |
* it and/or modify it under the terms of the GNU General Public |
23 |
* License as published by the Free Software Foundation; either |
24 |
* version 2 of the License, or (at your option) any later version. |
25 |
* |
26 |
* The ASCEND Modeling Library is distributed in hope that it |
27 |
* will be useful, but WITHOUT ANY WARRANTY; without even the implied |
28 |
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
29 |
* See the GNU General Public License for more details. |
30 |
* |
31 |
* You should have received a copy of the GNU General Public License |
32 |
* along with the program; if not, write to the Free Software |
33 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check |
34 |
* the file named COPYING. |
35 |
*) |
36 |
|
37 |
(*============================================================================* |
38 |
|
39 |
B V P . A 4 L |
40 |
------------- |
41 |
|
42 |
AUTHORS: Ben Allan |
43 |
Peter Piela |
44 |
Boyd T. Safrit |
45 |
Joseph J. Zaher |
46 |
|
47 |
DATES: 07/91 - Original code. |
48 |
08/94 - Added the observations to LSODE. |
49 |
09/94 - Added ivp as base type for all initial value problem |
50 |
solvers. baa. |
51 |
10/94 - Added other integration methods to supplement lsode |
52 |
and provide a means for dynamic optimization. |
53 |
04/96 - Modified for the use of constants and function abs |
54 |
03/97 - Decoupled from IVP, rewritten in ASCEND IV. |
55 |
|
56 |
CONTENTS: The bvp_point model definition that is required |
57 |
in the integration model. |
58 |
For boundary value |
59 |
problems and for dynamic optimization, a general integration |
60 |
model is supplied which enables users to specify any of a |
61 |
number of alternative integration techniques. The user |
62 |
should be aware, however, that using the general integration |
63 |
model will substantially increase the size of a problem. |
64 |
When possible, an IVP library is preferable to use. |
65 |
|
66 |
*) |
67 |
|
68 |
MODEL bvp_base REFINES cmumodel; |
69 |
NOTES 'purpose' SELF { |
70 |
This MODEL anchors the boundary value problem library. |
71 |
This library allows you to solve differential/algebraic |
72 |
equation systems using standard collocation methods. |
73 |
See example bvp_test. |
74 |
} |
75 |
END NOTES; |
76 |
END bvp_base; |
77 |
(* *********************************************************** *) |
78 |
(* ****** bvp_point: the collocation user MODEL interface *** *) |
79 |
(* *********************************************************** *) |
80 |
MODEL bvp_point REFINES bvp_base; |
81 |
NOTES 'purpose' SELF { |
82 |
Generic definition of the differential equation system, |
83 |
Dy[i] = dydx[i], i=1..n_eq, D = d/dx. |
84 |
Create a refinement of this type that includes a part which |
85 |
is your DAE MODEL and merge your variables with x,y,dydx as |
86 |
needed. See MODEL bvp_test for an example. |
87 |
Your refinement should define all the standard methods |
88 |
default_self, etc. |
89 |
} |
90 |
'usage' SELF { |
91 |
Note that the integration will behave much better if the |
92 |
typical values of your state variables are all about the |
93 |
same size. Integrators can lie if you give them poorly |
94 |
scaled problems. Dimensionless variables are generally best |
95 |
to use if you can easily formulate your MODEL in those |
96 |
terms. |
97 |
} |
98 |
END NOTES; |
99 |
|
100 |
n_eq "number of implicit ODE's" IS_A integer_constant; |
101 |
|
102 |
dydx[1..n_eq] "derivative variables", |
103 |
y[1..n_eq] "state variables", |
104 |
x "independent variable" |
105 |
IS_A solver_var; |
106 |
|
107 |
METHODS |
108 |
|
109 |
METHOD default_self; |
110 |
(* do not assign anything as these are merged with |
111 |
* user's variables which are all assigned. |
112 |
*) |
113 |
END default_self; |
114 |
|
115 |
METHOD specify; |
116 |
(* The state variables are set |
117 |
* TRUE, while their derivatives are FALSE. |
118 |
*) |
119 |
x.fixed := TRUE; |
120 |
y[1..n_eq].fixed := TRUE; |
121 |
dydx[1..n_eq].fixed := FALSE; |
122 |
END specify; |
123 |
END bvp_point; |
124 |
|
125 |
|
126 |
(* ******************************************************************** *) |
127 |
(* ********************* bvp internal models ************************* *) |
128 |
(* ******************************************************************** *) |
129 |
|
130 |
MODEL propagation( |
131 |
n_point WILL_BE integer_constant; |
132 |
eval[0..n_point] WILL_BE bvp_point; |
133 |
n_eq WILL_BE integer_constant; |
134 |
) WHERE ( |
135 |
n_eq == eval[0].n_eq; |
136 |
) REFINES bvp_base; |
137 |
(* eval[0..n_point] ARE_ALIKE; |
138 |
* Eval[i] must be deeply alike, so use of ARE_ALIKE here is heuristic at best. |
139 |
* Formal type compatibility does not ensure a well defined BVP. |
140 |
* No longer an issue, since eval is coming in from outside where it |
141 |
* was constructed all at the same time. |
142 |
*) |
143 |
|
144 |
NOTES |
145 |
'purpose' SELF { |
146 |
This MODEL does nothing by itself, and should never be created. |
147 |
Only the refinements of this MODEL should be created. |
148 |
If you need a new collocation formula, create it by refining |
149 |
propagation and then update the SELECT statement in |
150 |
the MODEL integration. |
151 |
} |
152 |
'usage' n_order { |
153 |
n_order did nothing. |
154 |
It was mainly a carrier of information for the user. |
155 |
Specifically, it gives the order of the error of the collocation. |
156 |
in terms of h. |
157 |
this information should just be kept in NOTES instead, like so. |
158 |
} |
159 |
END NOTES; |
160 |
|
161 |
|
162 |
h IS_A solver_var; |
163 |
(* propagate the dimensionality of x to h, though the |
164 |
h, eval[0].x ARE_ALIKE; |
165 |
* ASCEND environment would do the same thing for us automagically. |
166 |
* We actually couldn't care less about the type of h, so |
167 |
* long as it is dimensionally consistent with the x. |
168 |
* or we could do it with an assignment: |
169 |
h := eval[0].x; |
170 |
*) |
171 |
initial ALIASES eval[0]; |
172 |
final ALIASES eval[n_point]; |
173 |
final.x = initial.x + h; |
174 |
|
175 |
METHODS |
176 |
METHOD specify; |
177 |
RUN eval[0..n_point].specify; |
178 |
h.fixed := TRUE; |
179 |
final.x.fixed := FALSE; |
180 |
eval[1..n_point].y[1..n_eq].fixed := FALSE; |
181 |
eval[1..n_point].x.fixed := FALSE; |
182 |
END specify; |
183 |
END propagation; |
184 |
|
185 |
MODEL euler( |
186 |
n_point WILL_BE integer_constant; |
187 |
eval[0..n_point] WILL_BE bvp_point; |
188 |
n_eq WILL_BE integer_constant; |
189 |
) WHERE ( |
190 |
n_eq == eval[0].n_eq; |
191 |
n_point == 1; |
192 |
) REFINES propagation(); |
193 |
|
194 |
NOTES |
195 |
'order of error' SELF { |
196 |
The error in the euler method is O(h). |
197 |
} |
198 |
END NOTES; |
199 |
|
200 |
FOR i IN [1..n_eq] CREATE |
201 |
eval[1].y[i] = eval[0].y[i] + h*eval[0].dydx[i]; |
202 |
END FOR; |
203 |
|
204 |
METHODS |
205 |
(* specify inherited from propagation is correct *) |
206 |
(* |
207 |
METHOD specify; |
208 |
RUN eval[0..n_point].specify; |
209 |
h.fixed := TRUE; |
210 |
final.x.fixed := FALSE; |
211 |
eval[1..n_point].y[1..n_eq].fixed := FALSE; |
212 |
eval[1..n_point].x.fixed := FALSE; |
213 |
END specify; |
214 |
*) |
215 |
|
216 |
END euler; |
217 |
|
218 |
MODEL trapezoid( |
219 |
n_point WILL_BE integer_constant; |
220 |
eval[0..n_point] WILL_BE bvp_point; |
221 |
n_eq WILL_BE integer_constant; |
222 |
) WHERE ( |
223 |
n_eq == eval[0].n_eq; |
224 |
n_point == 1; |
225 |
) REFINES propagation(); |
226 |
|
227 |
NOTES |
228 |
'order of error' SELF { |
229 |
The error in the trapezoidal rule is O(h^2). |
230 |
} |
231 |
END NOTES; |
232 |
|
233 |
FOR i IN [1..n_eq] CREATE |
234 |
eval[1].y[i] = eval[0].y[i] + 0.5*h* |
235 |
(eval[0].dydx[i] + eval[1].dydx[i]); |
236 |
END FOR; |
237 |
|
238 |
METHODS |
239 |
(* specify inherited from propagation is correct *) |
240 |
(* |
241 |
METHOD specify; |
242 |
RUN eval[0..n_point].specify; |
243 |
h.fixed := TRUE; |
244 |
final.x.fixed := FALSE; |
245 |
eval[1..n_point].y[1..n_eq].fixed := FALSE; |
246 |
eval[1..n_point].x.fixed := FALSE; |
247 |
END specify; |
248 |
*) |
249 |
|
250 |
END trapezoid; |
251 |
|
252 |
MODEL midpoint( |
253 |
n_point WILL_BE integer_constant; |
254 |
eval[0..n_point] WILL_BE bvp_point; |
255 |
n_eq WILL_BE integer_constant; |
256 |
) WHERE ( |
257 |
n_eq == eval[0].n_eq; |
258 |
n_point == 2; |
259 |
) REFINES propagation(); |
260 |
|
261 |
NOTES |
262 |
'order of error' SELF { |
263 |
The error in the midpoint rule is O(h^2). |
264 |
} |
265 |
END NOTES; |
266 |
|
267 |
eval[1].x = initial.x + (1.0/2.0)*h; |
268 |
FOR i IN [1..n_eq] CREATE |
269 |
eval[1].y[i] = eval[0].y[i] + (1.0/2.0)*h* |
270 |
eval[0].dydx[i]; |
271 |
eval[2].y[i] = eval[0].y[i] + h* |
272 |
eval[1].dydx[i]; |
273 |
END FOR; |
274 |
|
275 |
METHODS |
276 |
(* specify inherited from propagation is correct *) |
277 |
(* |
278 |
METHOD specify; |
279 |
RUN eval[0..n_point].specify; |
280 |
h.fixed := TRUE; |
281 |
final.x.fixed := FALSE; |
282 |
eval[1..n_point].y[1..n_eq].fixed := FALSE; |
283 |
eval[1..n_point].x.fixed := FALSE; |
284 |
END specify; |
285 |
*) |
286 |
END midpoint; |
287 |
|
288 |
MODEL simpsons( |
289 |
n_point WILL_BE integer_constant; |
290 |
eval[0..n_point] WILL_BE bvp_point; |
291 |
n_eq WILL_BE integer_constant; |
292 |
) WHERE ( |
293 |
n_eq == eval[0].n_eq; |
294 |
n_point == 2; |
295 |
) REFINES propagation(); |
296 |
|
297 |
NOTES |
298 |
'order of error' SELF { |
299 |
The error in simpson's rule is O(h^4). |
300 |
} |
301 |
END NOTES; |
302 |
|
303 |
eval[1].x = initial.x + 0.5*h; |
304 |
FOR i IN [1..n_eq] CREATE |
305 |
eval[1].y[i] = eval[0].y[i] + 0.5*h* |
306 |
((5.0/12.0)*eval[0].dydx[i] + |
307 |
(8.0/12.0)*eval[1].dydx[i] - |
308 |
(1.0/12.0)*eval[2].dydx[i]); |
309 |
eval[2].y[i] = eval[0].y[i] + h* |
310 |
((1.0/6.0)*eval[0].dydx[i] + |
311 |
(4.0/6.0)*eval[1].dydx[i] + |
312 |
(1.0/6.0)*eval[2].dydx[i]); |
313 |
END FOR; |
314 |
|
315 |
METHODS |
316 |
(* specify inherited from propagation is correct *) |
317 |
(* |
318 |
METHOD specify; |
319 |
RUN eval[0..n_point].specify; |
320 |
h.fixed := TRUE; |
321 |
final.x.fixed := FALSE; |
322 |
eval[1..n_point].y[1..n_eq].fixed := FALSE; |
323 |
eval[1..n_point].x.fixed := FALSE; |
324 |
END specify; |
325 |
*) |
326 |
|
327 |
END simpsons; |
328 |
|
329 |
MODEL runge_kutta_gill( |
330 |
n_point WILL_BE integer_constant; |
331 |
eval[0..n_point] WILL_BE bvp_point; |
332 |
n_eq WILL_BE integer_constant; |
333 |
) WHERE ( |
334 |
n_eq == eval[0].n_eq; |
335 |
n_point == 4; |
336 |
) REFINES propagation(); |
337 |
|
338 |
NOTES |
339 |
'order of error' SELF { |
340 |
The error in the 4 point Runge-Kutta-Gill method is O(h^4). |
341 |
} |
342 |
END NOTES; |
343 |
|
344 |
eval[1].x = eval[2].x; |
345 |
eval[3].x = eval[4].x; |
346 |
eval[1].x = initial.x + 0.5*h; |
347 |
FOR i IN [1..n_eq] CREATE |
348 |
eval[1].y[i] = eval[0].y[i] + 0.5*h* |
349 |
eval[0].dydx[i]; |
350 |
eval[2].y[i] = eval[0].y[i] + 0.5*h* |
351 |
(0.41421356*eval[0].dydx[i] + |
352 |
0.58578644*eval[1].dydx[i]); |
353 |
eval[3].y[i] = eval[0].y[i] + h* |
354 |
(-0.707106781*eval[1].dydx[i] + |
355 |
1.707106781*eval[2].dydx[i]); |
356 |
eval[4].y[i] = eval[0].y[i] + h* |
357 |
(0.166666667*eval[0].dydx[i] + |
358 |
0.097631073*eval[1].dydx[i] + |
359 |
0.569035590*eval[2].dydx[i] + |
360 |
0.166666667*eval[3].dydx[i]); |
361 |
END FOR; |
362 |
|
363 |
METHODS |
364 |
(* specify inherited from propagation is correct *) |
365 |
(* |
366 |
METHOD specify; |
367 |
RUN eval[0..n_point].specify; |
368 |
h.fixed := TRUE; |
369 |
final.x.fixed := FALSE; |
370 |
eval[1..n_point].y[1..n_eq].fixed := FALSE; |
371 |
eval[1..n_point].x.fixed := FALSE; |
372 |
END specify; |
373 |
*) |
374 |
|
375 |
END runge_kutta_gill; |
376 |
|
377 |
MODEL gauss( |
378 |
n_point WILL_BE integer_constant; |
379 |
eval[0..n_point] WILL_BE bvp_point; |
380 |
n_eq WILL_BE integer_constant; |
381 |
) WHERE ( |
382 |
n_eq == eval[0].n_eq; |
383 |
n_point == 4; |
384 |
) REFINES propagation(); |
385 |
|
386 |
NOTES |
387 |
'order of error' SELF { |
388 |
The error in 4 point gauss method is O(h^6). |
389 |
} |
390 |
END NOTES; |
391 |
|
392 |
eval[1].x = initial.x + 0.11270167*h; |
393 |
eval[2].x = initial.x + 0.5*h; |
394 |
eval[3].x = initial.x + 0.88729833*h; |
395 |
FOR i IN [1..n_eq] CREATE |
396 |
eval[1].y[i] = initial.y[i] + 0.11270167*h* |
397 |
(1.23236*eval[1].dydx[i] - |
398 |
0.31922*eval[2].dydx[i] + |
399 |
0.08686*eval[3].dydx[i]); |
400 |
eval[2].y[i] = initial.y[i] + 0.5*h* |
401 |
(0.60053*eval[1].dydx[i] + |
402 |
0.44444*eval[2].dydx[i] - |
403 |
0.04497*eval[3].dydx[i]); |
404 |
eval[3].y[i] = initial.y[i] + 0.88729833*h* |
405 |
(0.30203*eval[1].dydx[i] + |
406 |
0.54144*eval[2].dydx[i] + |
407 |
0.15653*eval[3].dydx[i]); |
408 |
eval[4].y[i] = initial.y[i] + h* |
409 |
(0.27778*eval[1].dydx[i] + |
410 |
0.44444*eval[2].dydx[i] + |
411 |
0.27778*eval[3].dydx[i]); |
412 |
END FOR; |
413 |
|
414 |
METHODS |
415 |
(* specify inherited from propagation is correct *) |
416 |
(* |
417 |
METHOD specify; |
418 |
RUN eval[0..n_point].specify; |
419 |
h.fixed := TRUE; |
420 |
final.x.fixed := FALSE; |
421 |
eval[1..n_point].y[1..n_eq].fixed := FALSE; |
422 |
eval[1..n_point].x.fixed := FALSE; |
423 |
specify; |
424 |
*) |
425 |
|
426 |
END gauss; |
427 |
|
428 |
MODEL lobatto( |
429 |
n_point WILL_BE integer_constant; |
430 |
eval[0..n_point] WILL_BE bvp_point; |
431 |
n_eq WILL_BE integer_constant; |
432 |
) WHERE ( |
433 |
n_eq == eval[0].n_eq; |
434 |
n_point == 4; |
435 |
) REFINES propagation(); |
436 |
|
437 |
NOTES |
438 |
'order of error' SELF { |
439 |
The error in the 4 lobatto point method is O(h^8). |
440 |
} |
441 |
END NOTES; |
442 |
|
443 |
eval[1].x = initial.x + 0.11270167*h; |
444 |
eval[2].x = initial.x + 0.5*h; |
445 |
eval[3].x = initial.x + 0.88729833*h; |
446 |
FOR i IN [1..n_eq] CREATE |
447 |
eval[1].y[i] = initial.y[i] + 0.11270167*h* |
448 |
(0.428010*eval[0].dydx[i] + |
449 |
0.602339*eval[1].dydx[i] - |
450 |
0.044301*eval[2].dydx[i] + |
451 |
0.029587*eval[3].dydx[i] - |
452 |
0.015635*eval[4].dydx[i]); |
453 |
eval[2].y[i] = initial.y[i] + 0.5*h* |
454 |
(-0.06250*eval[0].dydx[i] + |
455 |
0.68122*eval[1].dydx[i] + |
456 |
0.44444*eval[2].dydx[i] - |
457 |
0.12566*eval[3].dydx[i] + |
458 |
0.06250*eval[4].dydx[i]); |
459 |
eval[3].y[i] = initial.y[i] + 0.88729833*h* |
460 |
(0.001986*eval[0].dydx[i] + |
461 |
0.309303*eval[1].dydx[i] + |
462 |
0.506524*eval[2].dydx[i] + |
463 |
0.236552*eval[3].dydx[i] - |
464 |
0.054365*eval[4].dydx[i]); |
465 |
eval[4].y[i] = initial.y[i] + h* |
466 |
(0.277778*eval[1].dydx[i] + |
467 |
0.444444*eval[2].dydx[i] + |
468 |
0.277778*eval[3].dydx[i]); |
469 |
END FOR; |
470 |
|
471 |
METHODS |
472 |
(* specify inherited from propagation is correct *) |
473 |
(* |
474 |
METHOD specify; |
475 |
RUN eval[0..n_point].specify; |
476 |
h.fixed := TRUE; |
477 |
final.x.fixed := FALSE; |
478 |
eval[1..n_point].y[1..n_eq].fixed := FALSE; |
479 |
eval[1..n_point].x.fixed := FALSE; |
480 |
END specify; |
481 |
*) |
482 |
|
483 |
END lobatto; |
484 |
|
485 |
MODEL integration( |
486 |
nstep IS_A integer_constant; |
487 |
npoint IS_A integer_constant; |
488 |
method IS_A symbol_constant; |
489 |
grid[0..nstep*npoint] WILL_BE bvp_point; |
490 |
stepsize WILL_BE solver_var; |
491 |
n_eq IS_A integer_constant; |
492 |
) WHERE ( |
493 |
((method == 'Euler') AND (npoint == 1)) OR |
494 |
((method == 'trapezoidal') AND (npoint == 1)) OR |
495 |
((method == 'midpoint') AND (npoint == 2)) OR |
496 |
((method == 'Simpsons') AND (npoint == 2)) OR |
497 |
((method == 'Runge-Kutta-Gill') AND (npoint == 4)) OR |
498 |
((method == 'Gauss') AND (npoint == 4)) OR |
499 |
((method == 'Lobatto') AND (npoint == 4)); |
500 |
) REFINES bvp_base; |
501 |
|
502 |
NOTES 'usage' SELF { |
503 |
This writes the equations for a mesh with nstep collocation |
504 |
intervals. In each interval there npoint nodes. |
505 |
The total mesh has (nstep * npoint + 1) nodes. |
506 |
|
507 |
In order to use this MODEL, create a refinement of bvp_point |
508 |
that contains the MODEL you want to integrate, then create |
509 |
an array of them (grid) and pass it in along with the other options. |
510 |
See the MODEL bvp_point for details of how to do this. |
511 |
See the MODELs bvp_test and bvp_dynamics for an example. |
512 |
} |
513 |
END NOTES; |
514 |
(* cook up the little arrays for propagation out of the |
515 |
* big array from the user. |
516 |
*) |
517 |
FOR i IN [0..nstep-1] CREATE |
518 |
step_nodes[i+1][pset[i]] ALIASES |
519 |
(grid[(i*npoint)..((i+1)*npoint)]) |
520 |
WHERE pset[i] IS_A set OF integer_constant WITH_VALUE |
521 |
(0..npoint); |
522 |
END FOR; |
523 |
|
524 |
(* merge all the sets. we need a better way of |
525 |
* getting at the set defined for an array. |
526 |
* we could get by without the merge. |
527 |
*) |
528 |
pset[0..nstep-1] ARE_THE_SAME; |
529 |
|
530 |
(* create the generic step stuctures and refine to rule requested *) |
531 |
FOR i IN [1..nstep] CREATE |
532 |
step[i] IS_A propagation(npoint,step_nodes[i],n_eq); |
533 |
END FOR; |
534 |
|
535 |
(* refine to rule *) |
536 |
SELECT (method) |
537 |
CASE 'Euler': |
538 |
FOR i IN [1..nstep] CREATE |
539 |
step[i] IS_REFINED_TO |
540 |
euler(npoint,step_nodes[i],n_eq); |
541 |
END FOR; |
542 |
CASE 'trapezoidal': |
543 |
FOR i IN [1..nstep] CREATE |
544 |
step[i] IS_REFINED_TO |
545 |
trapezoid(npoint,step_nodes[i],n_eq); |
546 |
END FOR; |
547 |
CASE 'midpoint': |
548 |
FOR i IN [1..nstep] CREATE |
549 |
step[i] IS_REFINED_TO |
550 |
midpoint(npoint,step_nodes[i],n_eq); |
551 |
END FOR; |
552 |
CASE 'Simpsons': |
553 |
FOR i IN [1..nstep] CREATE |
554 |
step[i] IS_REFINED_TO |
555 |
simpsons(npoint,step_nodes[i],n_eq); |
556 |
END FOR; |
557 |
CASE 'Runge-Kutta-Gill': |
558 |
FOR i IN [1..nstep] CREATE |
559 |
step[i] IS_REFINED_TO |
560 |
runge_kutta_gill(npoint,step_nodes[i],n_eq); |
561 |
END FOR; |
562 |
CASE 'Gauss': |
563 |
FOR i IN [1..nstep] CREATE |
564 |
step[i] IS_REFINED_TO |
565 |
gauss(npoint,step_nodes[i],n_eq); |
566 |
END FOR; |
567 |
CASE 'Lobatto': |
568 |
FOR i IN [1..nstep] CREATE |
569 |
step[i] IS_REFINED_TO |
570 |
lobatto(npoint,step_nodes[i],n_eq); |
571 |
END FOR; |
572 |
END SELECT; |
573 |
|
574 |
|
575 |
METHODS |
576 |
METHOD default_self; |
577 |
RUN values; |
578 |
END default_self; |
579 |
METHOD values; |
580 |
step[1..nstep].h := stepsize; |
581 |
END values; |
582 |
METHOD specify; |
583 |
stepsize.fixed := TRUE; |
584 |
FOR i IN [1..nstep] DECREASING DO |
585 |
RUN step[i].specify; |
586 |
END FOR; |
587 |
END specify; |
588 |
|
589 |
END integration; |
590 |
|
591 |
(************************************************************************) |
592 |
(************** demo and test models ************************************) |
593 |
(************************************************************************) |
594 |
MODEL testbvp_base REFINES testcmumodel; |
595 |
END testbvp_base; |
596 |
|
597 |
MODEL test_dynamics REFINES testbvp_base; |
598 |
x IS_A factor; |
599 |
t IS_A time; |
600 |
xdot IS_A frequency; |
601 |
xdot = 2{1/s} * x * exp(-2{1/s}*t) * cos(t*1{rad/s}); |
602 |
METHODS |
603 |
METHOD default_self; |
604 |
RUN values; |
605 |
END default_self; |
606 |
METHOD specify; |
607 |
x.fixed := TRUE; |
608 |
xdot.fixed := FALSE; |
609 |
t.fixed := TRUE; |
610 |
END specify; |
611 |
METHOD values; |
612 |
xdot.lower_bound := -1e6{1/s}; |
613 |
END values; |
614 |
END test_dynamics; |
615 |
|
616 |
MODEL dynamic_point REFINES bvp_point; |
617 |
|
618 |
n_eq :== 1; (* you can have as many as you like *) |
619 |
|
620 |
(* replace the following line with an IS_A of your MODEL *) |
621 |
your_model IS_A test_dynamics; |
622 |
|
623 |
(* connect independent variables. If your MODEL is autonomous, |
624 |
* you don't need to, but then you must call |
625 |
* bvp_point::clear and bvp_point::specify in your methods |
626 |
* to get x set properly. |
627 |
*) |
628 |
x, your_model.t ARE_THE_SAME; |
629 |
|
630 |
(* connect your variables to the integration state variables *) |
631 |
y[1], your_model.x ARE_THE_SAME; |
632 |
|
633 |
(* connect your variables to the integration derivatives *) |
634 |
dydx[1], your_model.xdot ARE_THE_SAME; |
635 |
|
636 |
METHODS |
637 |
|
638 |
METHOD specify; |
639 |
|
640 |
RUN your_model.specify; |
641 |
(* If you write your_model correctly, you don't need |
642 |
to run bvp_point::specify because you've wired all |
643 |
the bvp variables into some of yours. |
644 |
(Not TRUE if your MODEL is autonomous, though). |
645 |
RUN bvp_point::specify; |
646 |
*) |
647 |
|
648 |
END specify; |
649 |
END dynamic_point; |
650 |
|
651 |
|
652 |
MODEL bvp_test REFINES testbvp_base; |
653 |
stepsize IS_A time; |
654 |
npoint, nstep IS_A integer_constant; |
655 |
npoint :== 1; |
656 |
nstep :== 100; |
657 |
nodes[0..nstep*npoint] IS_A dynamic_point; |
658 |
initial ALIASES nodes[0]; |
659 |
final ALIASES nodes[nstep*npoint]; |
660 |
integral IS_A |
661 |
integration(nstep,npoint,'Euler',nodes,stepsize,initial.n_eq); |
662 |
|
663 |
(* we don't tie the test MODEL to the ASCEND plot MODEL *) |
664 |
|
665 |
METHODS |
666 |
METHOD default_self; |
667 |
stepsize := 0.05{s}; |
668 |
initial.x := 0{s}; |
669 |
initial.y[1] := 1; |
670 |
RUN nodes[0..nstep*npoint].your_model.default_self; |
671 |
RUN integral.default_self; |
672 |
END default_self; |
673 |
METHOD specify; |
674 |
stepsize.fixed := TRUE; |
675 |
RUN integral.specify; |
676 |
END specify; |
677 |
METHOD values; |
678 |
stepsize := 0.05{s}; |
679 |
initial.x := 0{s}; |
680 |
initial.y[1] := 1; |
681 |
RUN nodes[0..nstep*npoint].your_model.values; |
682 |
RUN integral.values; |
683 |
END values; |
684 |
|
685 |
END bvp_test; |