|
|
K. Taubert, W. Wiedl: Matlab Differentialgleichungen |
y1' = -y1*(alpha*y2 + beta) + gamma y2' = y2*(rho*y1 - sigma) + tau*(1+y1)mit den Anfangswerten:
y1(0) = -1, y2(0) = 0und den Parameterwerten:
alpha=1.5e-18, beta=2.5e-6, gamma=2.1e-6, rho=0.6, sigma=0.18, tau=0.016beschreibt das Modell eines Ruby Oszillators, wobei y(2) die Dichte der Photonen und y(1) die dimensionslose 'population inversion' angibt.
function w = DLOM(t,y,flag)
% Laser Oscillator Model
alpha = 1.5e-18;
beta = 2.5e-6;
gamma = 2.1e-6;
rho = 0.6;
sigma = 0.18;
tau = 0.016;
switch flag
case ''
w = [ -y(1)*(alpha*y(2)+beta)+gamma;
y(2)*(rho*y(1)-sigma)+tau*(1+y(1))];
case 'jacobian'
w = [ -(alpha*y(2)+beta), -y(1)*alpha ;
y(2)*rho + tau, (rho*y(1)-sigma) ];
end
wobei wir die Routine schon so geschrieben haben, daß sie auch die
Jacobi Matrix berechnen kann.
Szenario 1:
Physikalische Gründe lassen über dem Integrationsintervall den folgenden
Verlauf erwarten. Dieser Verlauf weist deutlich zwei Phasen auf.
Im ersten Teil des Intervalls findet man einen recht einfachen Verlauf der
Lösungskurven. Die Jacobi-Matrix hat am Startpunkt t=0, y=[-1 0] die
Eigenwerte [-2.5e-6 -7.8e-1] und damit ein Steifigkeitsverhältnis von
3.0e+5. Viele Voraussetzungen für ein steifes Problem sind damit gegeben.
Man wird diesen Teil z.B. mit ode15s integrieren.
Im zweiten Teil des Intervalls erfordert die Integration des Systems vermutlich
von jedem Integrator erheblichen Aufwand. Steife Integratoren werden hier nicht
von Vorteil sein. ode45 dürfte hier die erste Wahl sein.
Wir gehen hier davon aus, daß bekannt ist, daß der Wechsel
vom steifen zum nicht-steifen Integrator bei 4.95e+5 zu erfolgen hat,
dies ist ungefähr die Stelle, an der das System zu schwingen beginnt.
Der Matlab-Code mit dem Integrator-Aufruf lautet dann:
opt = odeset('AbsTol',1.0e-8,'RelTol',1.0e-5,'Jacobian','on');
tic;
[ta,ya] = ode15s('DLOM',[0 4.95e+5],[-1 0],opt);
n = length(ta);
opt = odeset(opt,'Jacobian','off');
[tb,yb] = ode45('DLOM',[ta(n) 1.0e6],ya(n,:),opt);
toc
t = [ta;tb];
ya(1,2) = ya(2,2);
y1 = [ya(:,1);yb(:,1)];
y2 = [ya(:,2);yb(:,2)];
plot(t,y1,t,log(y2));
Die Anweisung ya(1,2) = ya(2,2) soll lediglich verhindern, daß
der Logarithmus von 0 berechnet wird. Der plot Befehl liefert den
folgenden Verlauf.
Das unterschiedliche Verhalten in den beiden Teilen des Integrationsintervalles
macht sich auch bei den Eigenwerten der Jacobi-Matrix bemerkbar.
Der Realteil des einen Eigenwertes bleibt über
dem ganzen Intervall bei etwa -2.5e-6, der Betrag des anderen Realteils sackt
im ersten Teil des Integrationsintervalls von -7.8e-1 auf den Wert des
ersten ab und schwingt dann um diesen Wert.
Im ersten Teil des Intervalls sind die Eigenwerte reell, im zweiten treten periodisch
komplexe Eigenwerte auf, wobei Periode und Amplitude mit
zunehmenden t immer kleiner werden. Dasselbe gilt auch für die Schwingungen von phi.
Insgesamt kann man für die Integration einigen Aufwand erwarten und
es dürfte deshalb sinnvoll sein, für die beiden unterschiedlichen
Phasen verschiedene Integratoren zu benutzen. Dies setzt allerdings voraus,
daß man weiß, an welcher Stelle man von einem steifen zu
einem nicht-steifen Integrator wechseln sollte.
Andererseits scheint das System nicht derart aufwendig zu sein, daß
man das Problem nicht durchgehend mit ode45 integrieren könnte.
Durchlaufzeiten
| beide Intervalle | 0 bis 4.95e5 | 4.95e5 bis 1.0e6 | |
|---|---|---|---|
| ode45 | 406.70 | 379.29 | 27.41 |
| ode113 | 1138.70 | 1059.90 | 78.80 |
| ode15s | 831.23 | 1.85 | 829.38 |
| ode15s/Jacobian | 865.79 | 1.56 | 864.23 |
| ode15s/BDF | 1.93 | ||
| ode15s/Jacobian/BDF | 929.12 | 1.67 | |
| ode23s | (*) | 21.07 | (*) |
| ode23s/Jacobian | 11.82 |
Szenario 2:
Wenn man keine Vorstellungen über den Verlauf der Lösung und
die Eigenschaften des Systems hat, wird man in einem ersten Versuch
vermutlich ode45 als Integrator wählen und nach einiger Zeit die
Integration abbrechen, da sie zu lange dauert. Man wird in einem
solchen Falle auch eine Output Function verwenden, um etwas über
das Verhalten der Integratoren bei diesem System zu erfahren.
opt = odeset('AbsTol',1.0e-8,'RelTol',1.0e-5,'OutputFcn','odeprint');
[t,y] = ode45('DLOM',[0 1.0e6],[-1 0],opt);
Die Ausgabe von odeprint zeigt, daß ode45 zu Beginn der Integration
Schritte der Länge 1 macht.
Zum Vergleich probieren wir ode15s/Jacobian mit diesem Problem.
Als Integrationsintervall wählen wir 0 bis 100, als Output Funktion
'odeplot'. Die Graphikausgabe zeigt,
daß ode15s in diesem Startintervall schon Schrittweiten der
Länge 10 erreicht. Das vorliegende Problem könnte
steif sein.
Eine Berechnung der Eigenwerte der Jacoby-Matrix zur Zeit
t=0 ergibt -7.8e-1 und -2.5e-6, also ein Verhältnis von etwa
3e+5, so daß vieles für ein steifes Problem spricht.
Allerdings führt auch eine Integration mit ode15s/Jacobian nicht
rasch zum Ziel, so daß man sich genauer mit dem Problem
beschäftigen wird. Hat man ode15s/Jacobian mit einer Output Function,
etwa 'odeprint' laufen lassen, so hat man gesehen,daß die Integration
bis etwa 5.0e+5 problemlos ist.
Eine Möglichkeit wäre, daß
sich die Eigenschaften des Problems im Laufe des Integrationsintervalls
ändern, so daß man über einigen Teilintervallen
vorteilhaft mit steifen Integratoren, über anderen dagegen mit
nicht steifen Integratoren rechnen sollte.
Man kann nun bis 5.0e+5 oder 4.95e+5 einen steifen Integrator verwenden
und danach die Integration mit ode45 fortsetzen, was wir in Szenario 1
getan haben.
Falls die Übergangsstelle von steifer zu nicht-steifer Integration
aus den vorangegangenen Versuchen nicht klar ist, kann man versuchen,
sie mit Hilfe der Eigenwerte zu ermitteln, was bei diesem System nicht
allzu aufwendig ist. Wir verwenden dazu die Ereignissteuerung in den
Matlab Integratoren.
Wir haben gesehen, daß die Jacobi-Matrix zum Zeitpunkt t=0
eine Steifigkeitskoeffizienten von etwa 3e+5 aufweist und vermuten,
daß das Absinken dieses Koeffizienten dazu führt, daß
das System nach einiger Zeit nicht mehr steif ist. Wir integrieren
daher in einem ersten Schritt solange bis dieser Koeffizient kleiner
5.0 wir. Der betreffende Matlab-Code lautet:
opt = odeset('AbsTol',1.0e-8,'RelTol',1.0e-5);
Ival = [ -1; 0 ];
opt = odeset('AbsTol',1.0e-8,'RelTol',1.0e-5, ...
'Jacobian','on','Events','on');
[ta,ya,te] = ode15s('RubyODE',[0 1.0e+6],Ival,opt);
n = length(ta);
opt = odeset(opt,'Events','off');
[tb,yb] = ode45('RubyODE',[ta(n) 1.0e+6],ya(n,:),opt);
toc
te
Die verwendete ODE-Datei muß jetzt auch die Flagge 'events'
berücksichtigen und lautet:
function [w,ist,dir] = DLOM(t,y,flag)
% Laser Oscillator Model
alpha = 1.5e-18;
beta = 2.5e-6;
gamma = 2.1e-6;
rho = 0.6;
sigma = 0.18;
tau = 0.016;
switch flag
case ''
w = [ -y(1)*(alpha*y(2)+beta)+gamma;
y(2)*(rho*y(1)-sigma)+tau*(1+y(1))];
case 'jacobian'
w = [ -(alpha*y(2)+beta), -y(1)*alpha ;
y(2)*rho + tau, (rho*y(1)-sigma) ];
case 'events'
eiw = eig([ -(alpha*y(2)+beta), -y(1)*alpha ;
y(2)*rho + tau, (rho*y(1)-sigma) ]);
w = min(eiw)/max(eiw)-5.0;
ist= [1];
dir= [0];
end
Insgesamt benötigt die Integration jetzt eine Durchlaufzeit von
28.69 Sekunden und der Wechsel von steifer zu nicht-steifer Integration
erfolgt bei t=4.9037e+5.