Solveur de système d'Equations Différentielles Algébriques
y = dae(initial, t0, t, res) [y [,hd]] = dae(initial, t0, t [[,rtol], atol], res [,jac] [,hd]) [y, rd] = dae("root", initial, t0, t, res, ng, surface) [y, rd [,hd]] = dae("root", initial, t0, t [[,rtol], atol], res [,jac], ng, surface [,hd]) [y, rd] = dae("root2", initial, t0, t, res, ng, surface) [y, rd [,hd]] = dae("root2", initial, t0, t [[,rtol], atol], res [,jac], ng, surface [, psol, pjac] [, hd])
vecteur colonne. Peut valoir x0 ou
[x0;xdot0], où x0 est la
valeur de l'état au temps initial t0 et
xdot0 est la valeur (ou une estimation)
de l'état dérivé au temps initial (voir ci-après).
réel, le temps initial.
scalaire ou vecteur réel. Les instants auxquels la solution est voulue.
La solution peut s'obtenir à chaque étape de dae en initialisant
%DAEOPTIONS(2)=1
.
un scalaire ou vecteur colonne réel de même taille que
x0, la tolérance absolue de la solution.
Si atol est un vecteur, les tolérances
sont spécifiées pour chaque composante de l'état.
un scalaire ou vecteur colonne réel de même taille que
x0, la tolérance relative de la solution.
Si atol est un vecteur, les tolérances
sont spécifiées pour chaque composante de l'état.
une fonction external, calcule la valeur de
g(t,y,ydot). Peut être
Dans ce cas, sa séquence d'appel doit être
[r,ires]=res(t,x,xdot) et
res doit retourner le résidu
r=g(t,x,xdot) et un drapeau d'erreur
ires.
ires = 0 si
res est bien parvenu à calculer
r.
ires = -1 si le résidu est
localement non-défini pour g(t,x,xdot).
ires =-2 si le paramètres ne sont pas admissibles.
Cette forme d'external sert à passer des paramètres à la fonction. Elle doit se présenter comme suit:
list(res,p1,p2,...)
où la séquence d'appel de la fonction
res est
r=res(t,y,ydot,p1,p2,...)
res retourne toujours le résidu comme fonction de
(t,x,xdot,x1,x2,...), et
p1, p2,... sont des paramètres de la fonction.
Elle doit se référer au nom d'une routine C ou Fortran.
Supposant que <r_name> est le nom donné,
La séquence d'appel en Fortran doit être
<r_name>(t,x,xdot,res,ires,rpar,ipar)
double precision
t,x(*),xdot(*),res(*),rpar(*)
integer ires,ipar(*)
La séquence d'appel en C doit être
C2F(<r_name>)(double *t, double *x, double
*xdot, double *res, integer *ires, double *rpar, integer
*ipar)
où
t est la valeur actuelle du temps
x est la valeur de l'état
xdot est la valeur de l'état dérivé
res la valeur du résidu
ires indicateur de complétion
rpar est un vecteur de paramètres nécéssaires
mais non initialisables par dae.
ipar est un vecteur de paramètres entiers
nécéssaires mais non initialisables par dae
une fonction external, calcule la valeur de
dg/dx+cj*dg/dxdot pour un paramètre
cj donné. Elle peut être:
Sa séquence d'appel doit être
r=jac(t,x,xdot,cj) et la fonction
jac doit retourner
r=dg(t,x,xdot)/dy+cj*dg(t,x,xdot)/dxdot
où cj est un scalaire réel.
Cette forme d'external est utilisée pour passer des paramètres à la fonction. Elle doit se présenter comme suit :
list(jac,p1,p2,...)
où la séquence d'appel de la fonction
jac est
r=jac(t,x,xdot,p1,p2,...)
jac retourne toujours
dg/dx+cj*dg/dxdot comme fonction de
(t,x,xdot,cj,p1,p2,...).
elle doit se référer au nom d'une routine C ou Fortran. Supposant que <j_name> est le nom donné,
La séquence d'appel en Fortran doit être
<j_name>(t, x, xdot, r, cj, ires,
rpar, ipar)
double precision t, x(*), xdot(*), r(*),
ci, rpar(*)
integer ires, ipar(*)
La séquence d'appel en C doit être
C2F(<j_name>)(double *t, double *x, double
*xdot, double *r, double *cj, integer *ires, double *rpar, integer *ipar)
où t, x, xdot, ires, rpar, ipar
ont la même définition qu'au-dessus, r
est la valeur du résultat
une fonction external, calcule a valeur du vecteur colonne
surface(t,x) à ng éléments.
Chaque élément définit une surface. Elle peut être
Sa séquence d'appel doit être
r=surface(t,x), cette fonction doit retourner
un vecteur colonne à ng éléments.
Cette forme d'external est utilisé pour passer des paramètres à la fonction. Elle doit se présenter comme suit :
list(surface,p1,p2,...)
où la qéquence d'appel de la fonction
surface est
r=surface(t,x,p1,p2,...)
elle doit se référer au nom d'une routine C ou Fortran. Supposant que <s_name> est le nom donné,
La séquence d'appel en Fortran doit être
<s_name>(nx, t, x, ng, r, rpar,
ipar)
double precision t, x(*), r(*),
rpar(*)
integer nx, ng,ipar(*)
La séquence d'appel en C doit être
C2F(<s_name>)(double *t, double *x, double
*xdot, double *r, double *cj, integer *ires, double *rpar, integer *ipar)
où t, x, rpar, ipar ont les mêmes définitions qu'au-dessus,
ng est le nombre de surfaces,
nx est la dimension de l'état et
r est le vecteur résultat.
un vecteur à deux entrées [times num] où
times est la valeur des temps auquel les surfaces sont traversées,
num est le nombre de surfaces traversées.
external (fonction, liste or chaîne de caractères). Voir daskr
external (fonction, liste or chaîne de caractères). Voir daskr
vecteur réel, stocke en sortie le contexte de
dae. Peut être utilisé comme paramètre d'entrée
pour reprendre l'intégration (reprise à chaud).
matrice réelle. Si
%DAEOPTIONS(2)=1
,
chaque colonne est le vecteur [t;x(t);xdot(t)] où
t est le temps auquel la solution à été calculée.
Sinon y est le vecteur
[x(t);xdot(t)].
La fonction dae est une gateway construite sur les solveurs
dassl, dasrt
et daskr
destinés à l'intégration implicite d'équations différentielles.
L'option "root" appelle la routine dasrt,
et "root2" appelle daskr.
g(t, x, xdot) = 0 x(t0) = x0 and xdot(t0) = xdot0
Si xdot0 n'est pas donné en paramètre initial,
dae tente de la calculer en résolvant
g(t,x0,xdot0)=0.
Si xdot0 est donné en paramètre initial, il peut soit
satifaire g(t,x0,xdot0)=0, soit en être une approximation.
Dans le dernier cas,
%DAEOPTIONS(7) doit être initialisé à 1.
Des exemples détaillés utilisant des externals codées en C et en Scilab se trouvent dans
modules/differential_equations/tests/unit_tests/dassldasrt.tst et
modules/differential_equations/tests/unit_tests/daskr.tst
Exemple #1: dassl (pas de traversée de surface)
// Exemple avec du code Scilab //-------------------------------------------------- function [r, ires]=chemres(t, y, yd) r(1) = -0.04*y(1) + 1d4*y(2)*y(3) - yd(1); r(2) = 0.04*y(1) - 1d4*y(2)*y(3) - 3d7*y(2)*y(2) - yd(2); r(3) = y(1) + y(2) + y(3)-1; ires = 0; endfunction function pd=chemjac(x, y, yd, cj) pd = [-0.04-cj , 1d4*y(3) , 1d4*y(2); 0.04 ,-1d4*y(3)-2*3d7*y(2)-cj ,-1d4*y(2); 1 , 1 , 1 ] endfunction x0 = [1; 0; 0]; xd0 = [-0.04; 0.04; 0]; t = [1.d-5:0.02:.4, 0.41:.1:4, 40, 400, 4000, 40000, 4d5, 4d6, 4d7, 4d8, 4d9, 4d10]; y = dae([x0, xd0], 0, t, chemres); // Retourne les points d'observation demandés %DAEOPTIONS = list([], 1, [], [], [], 0, 0); // Demande à dae les points à retourner y = dae([x0, xd0], 0, 4d10, chemres); // Sans jacobian y = dae([x0, xd0], 0, 4d10, chemres, chemjac); // Avec jacobien | ![]() | ![]() |
Exemple #2: dasrt ("root")
// Exemple avec du code C (compilateur C requis) //-------------------------------------------------- bOK = haveacompiler(); if bOK <> %t [btn] = messagebox(["Vous avez besoin d''un compilateur C pour cet exemple."; "Arrêt de l''exécution."], "Problème de Software", "info"); return end //-1- Crée les codes C dans TMPDIR - équation de Vanderpol, forme implicite code = ['#include <math.h>' 'void res22(double *t, double *y, double *yd, double *res, int *ires, double *rpar, int *ipar)' '{res[0] = yd[0] - y[1];' ' res[1] = yd[1] - (100.0*(1.0 - y[0]*y[0])*y[1] - y[0]);}' ' ' 'void jac22(double *t, double *y, double *yd, double *pd, double *cj, double *rpar, int *ipar)' '{pd[0] = *cj - 0.0;' ' pd[1] = - (-200.0*y[0]*y[1] - 1.0);' ' pd[2] = - 1.0;' ' pd[3] = *cj - (100.0*(1.0 - y[0]*y[0]));}' ' ' 'void gr22(int *neq, double *t, double *y, int *ng, double *groot, double *rpar, int *ipar)' '{ groot[0] = y[0];}'] previous_dir = pwd(); cd TMPDIR; mputl(code, 't22.c') //-2- Compile et charge ilib_for_link(['res22' 'jac22' 'gr22'], 't22.c', [], 'c', [], 't22loader.sce'); exec('t22loader.sce') //-3- Exécute rtol = [1.d-6; 1.d-6]; atol = [1.d-6; 1.d-4]; t0 = 0; t = [20:20:200]; y0 = [2; 0]; y0d = [0; -2]; ng = 1; // Simulation simple t = 0:0.003:300; yy = dae([y0, y0d], t0, t, atol, rtol, 'res22', 'jac22'); clf(); plot(yy(1, :), yy(2, :)) // Trouve le premier point où yy(1) = 0 [yy, nn, hotd] = dae("root", [y0, y0d], t0, 300, atol, rtol, 'res22', 'jac22', ng, 'gr22'); plot(yy(1, 1), yy(2, 1), 'r+') xstring(yy(1, 1)+0.1, yy(2, 1), string(nn(1))); // Reprise à chaud pour le point suivant t01 = nn(1); [pp, qq] = size(yy); y01 = yy(2:3, qq); y0d1 = yy(3:4, qq); [yy, nn, hotd] = dae("root", [y01, y0d1], t01, 300, atol, rtol, 'res22', 'jac22', ng, 'gr22', hotd); plot(yy(1, 1), yy(2, 1), 'r+') xstring(yy(1, 1)+0.1, yy(2, 1), string(nn(1))); cd(previous_dir); | ![]() | ![]() |
Exemple #3: daskr ("root2"), avec les routines 'psol' et 'pjac' par défaut
// Exemple avec du code C (compilateur C requis) //-------------------------------------------------- bOK = haveacompiler(); if bOK <> %t [btn] = messagebox(["Vous avez besoin d''un compilateur C pour cet exemple."; "Arrêt de l''exécution."], "Problème de Software", "info"); return end //-1- Crée les codes C dans TMPDIR - équation de Vanderpol, forme implicite code = ['#include <math.h>' 'void res22(double *t, double *y, double *yd, double *res, int *ires, double *rpar, int *ipar)' '{res[0] = yd[0] - y[1];' ' res[1] = yd[1] - (100.0*(1.0 - y[0]*y[0])*y[1] - y[0]);}' ' ' 'void jac22(double *t, double *y, double *yd, double *pd, double *cj, double *rpar, int *ipar)' '{pd[0] = *cj - 0.0;' ' pd[1] = - (-200.0*y[0]*y[1] - 1.0);' ' pd[2] = - 1.0;' ' pd[3] = *cj - (100.0*(1.0 - y[0]*y[0]));}' ' ' 'void gr22(int *neq, double *t, double *y, int *ng, double *groot, double *rpar, int *ipar)' '{ groot[0] = y[0];}'] previous_dir = pwd(); cd TMPDIR; mputl(code, 't22.c') //-2- Compile et charge ilib_for_link(['res22' 'jac22' 'gr22'], 't22.c', [], 'c', [], 't22loader.sce'); exec('t22loader.sce') //-3- Exécute rtol = [1.d-6; 1.d-6]; atol = [1.d-6; 1.d-4]; t0 = 0; t = [20:20:200]; y0 = [2; 0]; y0d = [0; -2]; ng = 1; // Simulation simple t = 0:0.003:300; yy = dae([y0, y0d], t0, t, atol, rtol, 'res22', 'jac22'); clf(); plot(yy(1, :), yy(2, :)) // Trouve le premier point où yy(1) = 0 %DAEOPTIONS = list([] , 0, [], [], [], 0, [], 1, [], 0, 1, [], [], 1); [yy, nn, hotd] = dae("root2", [y0, y0d], t0, 300, atol, rtol, 'res22', 'jac22', ng, 'gr22', 'psol1', 'pjac1'); plot(yy(1, 1), yy(2, 1), 'r+') xstring(yy(1, 1)+0.1, yy(2, 1), string(nn(1))); // Reprise à chaud pour le point suivant t01 = nn(1); [pp, qq] = size(yy); y01 = yy(2:3, qq); y0d1 = yy(3:4, qq); [yy, nn, hotd] = dae("root2", [y01, y0d1], t01, 300, atol, rtol, 'res22', 'jac22', ng, 'gr22', 'psol1', 'pjac1', hotd); plot(yy(1, 1), yy(2, 1), 'r+') xstring(yy(1, 1)+0.1, yy(2, 1), string(nn(1))); cd(previous_dir); | ![]() | ![]() |
