WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

ODE: Änderung globale Variable nur bei Ausgabezeitpunkt

 

Nibbels
Forum-Newbie

Forum-Newbie


Beiträge: 3
Anmeldedatum: 07.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 07.11.2015, 16:07     Titel: ODE: Änderung globale Variable nur bei Ausgabezeitpunkt
  Antworten mit Zitat      
Hallo zusammen,

bin neu hier im Forum und habe ein Problem mit dem Solver ode15s.

Und zwar habe ich eine Differentialgleichung in eine Funktion gepackt und lasse sie mir dann von ode15s unter Vorgabe von Fehlertoleranzen lösen. Das funktioniert soweit auch ganz gut, nur stoße ich beim Verwenden von globalen Variablen auf das Problem, dass der solver bei jedem Rechenschritt eine globale Variable ändert, obwohl er noch nicht den richtigen Zeitwert zur Einhaltung der Toleranzen gefunden hat. Ich möchte aber, dass meine globale Variable e_norm_old nur bei allen Zeitpunkten meines Ausgabezeitvektor tsim geändert wird.

Ist das irgendwie möglich hinzubekommen?

Mein Befehl zum Lösen:
Code:

sim_options = odeset('RelTol',1e-5,'AbsTol',1e-8);
[tsim , xsim ] = ode15s(@(t,x) wurm3(t , x , par ),[tsim_start tsim_end],x,sim_options);
 


Und abgekürzt meine Funktion für die Differentialgleichung:
Code:

function x_out = wurm3( t , x , par )

global e_norm_old

x_out = zeros(7,1);

% Berechnung des Fehlers e
e = [ x(1) - x(3); x(3) - x(5) ];

% Gewichtskräfte
FGx0 = - par.m0 * par.g * sin(par.alpha);
FGx1 = - par.m1 * par.g * sin(par.alpha);
FGx2 = - par.m2 * par.g * sin(par.alpha);

% Federkräfte
Fc1 = par.c1*(x(1) - x(3) - par.l0);
Fc2 = par.c2*(x(3) - x(5) - par.l0);

% Dämpferkräfte
Fd1 = par.d1*(x(2) - x(4));
Fd2 = par.d2*(x(4) - x(6));


% Massenelement m0
x_out(1) = x(2);
x_out(2) = 1/par.m0 * ( -Fc1 - Fd1 + FGx0);

% Massenelement m1
x_out(3) = x(4);
x_out(4) = 1/par.m1 * ( -Fc2 + Fc1 - Fd2 + Fd1 + FGx1);

% Massenelement m2
x_out(5) = x(6);
x_out(6) = 1/par.m2 * ( +Fc2 + Fd2 + FGx2);


e_norm = norm(e);
x_out(7)  = fun_k_p( t , x(7) , e_norm , par );

e_norm_old = e_norm;

end
 



Ich hoffe, dass mein Problem verständlich beschrieben ist. Vielen Dank für eure Hilfe!
Private Nachricht senden Benutzer-Profile anzeigen


Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 07.11.2015, 17:11     Titel:
  Antworten mit Zitat      
Hallo,

mir stellt sich die Frage, warum du hier überhaupt mit globalen Variablen arbeitest. Wäre es nicht viel einfacher, wenn du die benötigten Informationen nachträglich aus der Rückgabe von ode15s berechnest?

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Nibbels
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 3
Anmeldedatum: 07.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 07.11.2015, 17:25     Titel:
  Antworten mit Zitat      
Hi Harald,

zunächst mal vielen Dank für deine Antwort. Ich arbeite mit der globalen Variable, weil ich die der folgenden Funktion prüfen muss, ob e_norm kleiner ist als e_norm_old:

Code:

function  k_p  = fun_k_p( t , k , e_norm , par )

global e_norm_old

% Eintrittszeit t_E
if e_norm_old >= par.lambda && e_norm < par.lambda
    t_E = t;
end

% k_p berechnen
if e_norm >= par.lambda+1
    k_p = par.gamma*(e_norm-par.lambda)^2;
   
elseif e_norm < par.lambda+1 && e_norm >= par.lambda
    k_p = par.gamma*sqrt((e_norm-par.lambda));
   
elseif e_norm < par.lambda && t-t_E < par.t_d
    k_p = 0;
   
elseif e_norm < par.lambda && t-t_E >= par.t_d
    k_p = -par.sigma*k;
   
else
    error('Nicht definierte Bedingung für e_norm')
end
 


Falls man das auch ohne globale Variable hinbekommt, wäre das natürlich noch besser.
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 07.11.2015, 18:25     Titel:
  Antworten mit Zitat      
Hallo,

es ist etwas schwer zu durchblicken, was der Code in der Gesamtheit erreichen soll.

Schau mal in der Doku von ode45 und odeset nach Events und OutputFcn.

Wenn du beobachten möchtest, ob etwas größer oder kleiner wird, könntest du auch eine zusätzliche DGL definieren und schauen, ob die Ableitung größer oder kleiner 0 ist.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Nibbels
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 3
Anmeldedatum: 07.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 10.11.2015, 11:31     Titel:
  Antworten mit Zitat      
Vielen Dank für deine Hilfe. Ich hab es mit der Eventfunktion hinbekommen. Diese sieht wie folgt aus:
Code:

function status = fun_ctrl_solve(t,y,~)

global e_norm e_norm_old

status = 0;

e_norm_old = e_norm;

end
 


Und der Aufruf:
Code:

sim_options = odeset('RelTol',1e-5,'AbsTol',1e-8,'OutputFcn',@fun_ctrl_solve);
[tsim , xsim ] = ode15s(@(t,x) wurm3(t , x , par ),[tsim_start tsim_end],x,sim_options);
 


Diese Funktion wird nach jedem erfolgreichem Integrationsschritt ausgeführt. Normalerweise sind diese Funktionen dazu gedacht, um eine Integration abzubrechen (bei Erreichen des Abbruchkriteriums setzt man im Code die Ausgangsgröße status auf 1). Damit es zu keinem Abbruch kommt, setze ich status generell auf 0 und meine erforderliche Zeile e_norm_old = e_norm wird somit nach jedem erfolgreichen Integrationsschritt ausgeführt.

Vielen Dank für die Hilfe!
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.