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

Integration mit variablen Grenzen

 

Feal

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 28.06.2021, 16:38     Titel: Integration mit variablen Grenzen
  Antworten mit Zitat      
Hallo zusammen,

ich komme aktuell bei der Integration einer Funktion nicht weiter. Bilder der Funktionen sind angehängt.
3.44 ist die Fouriertransformation eines Sinusburst mit Hanning-fensterung
Mit 3.46 lässt sich die monofrequente Funktion X_Mono durch Multiplikation und Integration mit 3.44 in eine bandbreitenabhängige Funktion überführen.

X_mono ähnelt dabei einer Sinc-Funktion und besteht aus rund 2000 Werten. Über einen "linearinterp" Fit und feval wandel ich die Daten in eine Funktion um:

Code:
   
[xData, yData] = prepareCurveData(f,abs(round_u_r_temp));
% Set up fittype and options.
 ft = 'linearinterp';
% Fit model to data.
[fitresult, ~] = fit( xData, yData, ft, 'Normalize', 'on' );
   
new_func = @(f) transpose(feval(fitresult,f)).*abs(X_tilde_f(f));
 


Zum Berechnen eines Wertes X_Band(f_0) muss ich diese Funktion mit der Gleichung 3.44 multiplizieren und über einen f_0 abhängigen Bereich integrieren.
Dieser Vorgang muss für rund 1500 f_0 Frequenzen wiederholt werden.
Wenn ich f_0 in der Funktion 3.44 als Vektor einsetze, kann ich das Integral für alle 1500 Werte auf einen Schlag berechnen.
z.B.
Code:

integral(new_func,30e3,70e3,'ArrayValued',true);
 

Problem dabei ist, dass die Grenzen (hier beispielhaft 30e3 und 70e3) von der Frequenz f_0 abhängen. Entsprechend müsste ich da Vektoren einfügen, die die Funktion aber leider nicht unterstützt.

Hat jemand eine Idee, wie ich das geschickt gelöst bekomme?

Meine aktuelle Notlösung ist mit trapz:

Code:

temp_e_band.(mode{i1}) = trapz(f,transpose(abs(epsilon_temp).*X_tilde_temp.*f_min_max_logic));
 


Wobei ich den "zu integrierenden Bereich" über eine Multiplikation mit einer Matrix aus 1en und 0en realisiere. Dies führt allerdings dazu, dass das Ergebnis stark von der Frequenzschrittweite abhängt und besonders bei niedrigen Frequenzen stark fehlerbehaftet ist.

Freue mich über hilfreiche Kommentare und Tipps

Bildschirmfoto 2021-06-28 um 17.21.02.png
 Beschreibung:

Download
 Dateiname:  Bildschirmfoto 2021-06-28 um 17.21.02.png
 Dateigröße:  17.32 KB
 Heruntergeladen:  178 mal
Bildschirmfoto 2021-06-28 um 17.19.39.png
 Beschreibung:

Download
 Dateiname:  Bildschirmfoto 2021-06-28 um 17.19.39.png
 Dateigröße:  25.69 KB
 Heruntergeladen:  168 mal


Harald
Forum-Meister

Forum-Meister


Beiträge: 24.495
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 29.06.2021, 21:15     Titel:
  Antworten mit Zitat      
Hallo,

im Zweifelsfall mit einer for-Schleife.
Sofern 'ArrayValued',true nicht notwendig ist, sollte man es weglassen.

Zu beachten ist, dass neben dem Integrationsfehler ein Interpolationsfehler eine Rolle spielt. Du kannst also nicht davon ausgehen, dass die Toleranzen von integral eingehalten werden.

Grüße,
Harald
_________________

1.) Ask MATLAB Documentation
2.) Search gomatlab.de, google.de or MATLAB Answers
3.) Ask Technical Support of MathWorks
4.) Go mad, your problem is unsolvable ;)
Private Nachricht senden Benutzer-Profile anzeigen
 
Feal

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.06.2021, 20:38     Titel:
  Antworten mit Zitat      
Hallo Harald,

danke für die Antwort.

"ArrayValued" wäre dann relevant, wenn ich alle Integrale auf einmal lösen könnte. Dafür bräuchte ich als variable Grenzen.

Das mit der for-Schleife hatte ich probiert. Rechenzeit explodiert dann leider und nur die Berechnung einer einzelnen Kurve dauert unter Umständen eine Minute.
Sprechen hier halt von 1000-2000 Integrationen pro Kurve und von denen gibt es in meist 4-12 Stück. Das macht im Vergleich zu aktuell, mit wenigen Sekunden für die komplette Berechnung, keinen Spaß mehr.

Beste Grüße
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.495
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 30.06.2021, 20:48     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
"ArrayValued" wäre dann relevant, wenn ich alle Integrale auf einmal lösen könnte.

... und wenn das Lösen aller Integrale auf einmal schon nicht geht, solltest du dieses "ArrayValued" eben weglassen.

Zitat:
nur die Berechnung einer einzelnen Kurve dauert unter Umständen eine Minute.

Zitat:
Das macht im Vergleich zu aktuell, mit wenigen Sekunden für die komplette Berechnung

Was denn nun? Wie kann es sein, dass eine komplette Berechnung wenige Sekunden dauert und eine nun "unter Umständen" (welche Umstände??) eine Minute?

Mangels Daten und zusammenhängendem Code ist das ganze nicht reproduzierbar und somit schwer nachvollziehbar. Wenn du durch die Verwendung von fit nicht signifikant an Genauigkeit oder so gewinnst, würde ich interp1 verwenden. Das dürfte deutlich schneller sein.

Zitat:
Sprechen hier halt von 1000-2000 Integrationen pro Kurve und von denen gibt es in meist 4-12 Stück.

Integrationen im Sinne von Aufrufen von integral ? Und wie kommen die 4-12 Stück ins Spiel??

Grüße,
Harald
_________________

1.) Ask MATLAB Documentation
2.) Search gomatlab.de, google.de or MATLAB Answers
3.) Ask Technical Support of MathWorks
4.) Go mad, your problem is unsolvable ;)
Private Nachricht senden Benutzer-Profile anzeigen
 
Feal

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.07.2021, 19:50     Titel:
  Antworten mit Zitat      
Hi,

aktuell schaut der Code so aus:
(die integral Funktion scheint allerdings doch zu gehen, siehe weiter unten...)

Code:

for i1 = 1:numel(mode) % jede Mode ist ein Kurvenverlauf der von monofrequent in bandbreitenabhängig umgewandelt werden soll
    f = f_moden.(mode{i1});   % Frequenzachse
    f_0_logic = f.*(1+2/burst) <= max(f); % Begrenzung der Frequenz (für die Berechnung von höheren Frequenzen fehlen Informationen)
    f_0 = f(f_0_logic)   % neue Frequenzachse für die zu berechnenden Werte
    f_band.(mode{i1}) = f_0;
    f_min = f_0.*(1-2/burst);   % minimale Frequenz die zur Berechnung der Frequenz f_0 notwendig ist
    f_max = f_0.*(1+2/burst);   % maximale Frequenz die zur Berechnung der Frequenz f_0 notwendig ist
    u_temp = u.(mode{i1});   % die umzuwandelnde physikalische Größe


% Funktion zum Berechnen der bandbreitenabhängigen Größe
% diese muss von f_min bis f_max integriert werden, dass man den neuen Wert für die Frequenz f_0 bekommt.
    X_tilde_f = @(f) n_p./(4*f_0') .* (sinc(n_p./(2*f_0').*(f-f_0')) + ...
        (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+f_0'))...
        + 0.5 * (sinc(n_p./(2*f_0') .* (f-(n_p-2)./n_p*f_0')) + ...
        (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+(n_p-2)./n_p*f_0'))) ...
        + 0.5 * (sinc(n_p./(2*f_0') .* (f-(n_p+2)./n_p*f_0')) + ...
        (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+(n_p+2)./n_p*f_0'))));
     
    X_tilde_temp = X_tilde_f(f);
    f_min_max_logic = and(f >= f_min', f <= f_max'); % Frequenzen zwischen f_min und f_max sind 1 und können anschließend durch trapz integriert werden
    temp_u_band.(mode{i1}) = trapz(f,transpose(abs(u_temp).*X_tilde_temp.*f_min_max_logic));
 


Für jede einzelne Frequenz (f_0) der neu zu berechnenden Kurve muss die Funktion von f_min bis f_max integriert werden.
Für 1600 Frequenzen (f_0), was einer Mode entspricht, braucht die Methode 200 ms.
Die Anzahl der Moden variiert und liegt meist zwischen 4 und 12 Stück.

Der Versuch die 1600 Frequenzen über eine for-Schleife zu berechnen hat etwa 30 Sekunden gedauert. Entsprechend war die Rechenzeit rund 150 mal länger.
Ein Problem war aber wohl, dass ich vom Herumprobieren noch "ArrayValued" auf true hatte. Das erhöht die Rechenzeit enorm. Habs jetzt mal kurz ohne programmiert, damit lande ich bei 1200 ms. Was zwar noch 6-mal länger ist, aber akzeptabel wäre. Die Erhöhung der Genauigkeit ist mehr als deutlich. Kurven passen nahezu perfekt.

Der Code schaut jetzt so aus:

Code:

    f_0_temp = f_0;
    u_temp = zeros(size(f_0_temp));
    for i2 = 1:length(f_0_temp)
        f_0 = f_0_temp(i2);
        X_tilde_f = @(f) n_p./(4*f_0') .* (sinc(n_p./(2*f_0').*(f-f_0')) + ...
            (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+f_0'))...
            + 0.5 * (sinc(n_p./(2*f_0') .* (f-(n_p-2)./n_p*f_0')) + ...
            (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+(n_p-2)./n_p*f_0'))) ...
            + 0.5 * (sinc(n_p./(2*f_0') .* (f-(n_p+2)./n_p*f_0')) + ...
            (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+(n_p+2)./n_p*f_0'))));
        new_func = @(f) transpose(feval(fitresult,f)).*abs(X_tilde_f(f));
        u_temp(i2) = integral(new_func,f_min(i2),f_max(i2),'ArrayValued',false);
    end
    temp_u_band.(mode{i1}) = u_temp;
 


Gibt es da noch eine Möglichkeit, dass ich neben f auch f_0 als Variable an die Funktion X_tilde_f übergeben kann und das auch bei "integral" berücksichtigt wird? Dann müsste ich die nicht immer neu erzeugen.
Bei der Funktion selbst wäre es ja einfach @(f,f_0).


Bereits jetzt vielen Dank für den Hinweis mit "ArrayValued". War mir nicht bewusst, dass das so einen großen Einfluss hat.

Beste Grüße
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.495
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 01.07.2021, 20:34     Titel:
  Antworten mit Zitat      
Hallo,

folgendes sollte ebenso gut gehen:
Code:
X_tilde_f = @(f, f_0) n_p./(4*f_0') .* (sinc(n_p./(2*f_0').*(f-f_0')) + ...
            (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+f_0'))...
            + 0.5 * (sinc(n_p./(2*f_0') .* (f-(n_p-2)./n_p*f_0')) + ...
            (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+(n_p-2)./n_p*f_0'))) ...
            + 0.5 * (sinc(n_p./(2*f_0') .* (f-(n_p+2)./n_p*f_0')) + ...
            (-1)^(n_p+1) * sinc(n_p./(2*f_0') .* (f+(n_p+2)./n_p*f_0'))));
    for i2 = 1:length(f_0_temp)
        f_0 = f_0_temp(i2);        
        new_func = @(f) transpose(feval(fitresult,f)).*abs(X_tilde_f(f,f0));
        u_temp(i2) = integral(new_func,f_min(i2),f_max(i2),'ArrayValued',false);
    end

"natürlich" ungetestet.

Und ja, "ArrayValued" kann einen enormen Unterschied machen. Das entscheidet, ob die zu integrierende Funktion für mehrere Stützstellen vektorisiert oder in einer for-Schleife ausgewertet wird.

Grüße,
Harald
_________________

1.) Ask MATLAB Documentation
2.) Search gomatlab.de, google.de or MATLAB Answers
3.) Ask Technical Support of MathWorks
4.) Go mad, your problem is unsolvable ;)
Private Nachricht senden Benutzer-Profile anzeigen
 
Feal

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 04.07.2021, 17:31     Titel:
  Antworten mit Zitat      
Hallo Harald,

die Variante funktioniert auch. Zeitlich quasi identisch.
Würde sagen, dass ich damit jetzt arbeiten kann Smile

Danke für die Unterstützung!

Beste Grüße
 
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 - 2024 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.