Numerische Auswertung des hochschwingenden Integrals


11

In diesem Fortgeschrittenenkurs über Anwendungen der komplexen Funktionstheorie wird an einer Stelle in einer Übung das hochschwingende Integral behandelt

I(λ)=cos(λcosx)sinxxdx

muss für große Werte von Verwendung der Sattelpunktmethode in der komplexen Ebene angenähert werden .λ

Aufgrund seiner starken Schwingung ist dieses Integral mit den meisten anderen Methoden sehr schwer zu bewerten. Dies sind zwei Fragmente des Graphen des Integranden für in verschiedenen Maßstäben:λ=10

cos (10 cos (x)) sin (x) / x

Eine asymptotische Näherung führender Ordnung ist

I1(λ)=cos(λ14π)2πλ

und eine weitere (viel kleinere) Verfeinerung fügt den Begriff hinzu

I2(λ)=18sin(λ14π)2πλ3

Ein Diagramm der angenäherten Werte als Funktion von sieht wie folgt aus:λ

Ich (Lambda) ca.

Nun kommt meine Frage: Um visuell zu sehen, wie gut die Approximation ist, möchte ich sie mit dem "realen Wert" des Integrals vergleichen, genauer gesagt mit einer guten Approximation desselben Integrals unter Verwendung eines unabhängigen Algorithmus. Aufgrund der geringen Korrektur der Unterführung würde ich erwarten, dass dies sehr nahe kommt.

Ich habe versucht, das Integral für einige mit anderen Algorithmen zu bewerten , aber mit sehr geringem Erfolg: Mathematica und Matlab mit dem standardmäßigen numerischen Integrator schaffen es nicht, einen aussagekräftigen Wert zu erzeugen (und dies explizit zu melden), mpmath mit beiden doppelt exponentiellen und die Gauß-Legendre-Methode führen zu sehr verrauschten Ergebnissen, obwohl sie leicht dazu neigt, um die Werte zu schwingen, die die Sattelpunktmethode liefert, wie dieses Diagramm zeigen kann:λtanh(sinh)

mpmath ca.

Schließlich versuchte ich mein Glück mit einem Monte-Carlo-Integrator unter Verwendung eines von mir implementierten Wichtigkeitsbeispiels, aber ich schaffte es auch nicht, stabile Ergebnisse zu erzielen.

Hat jemand eine Idee, wie dieses Integral unabhängig für einen festen Wert von oder so bewertet werden könnte ?λ>1


Ist die Funktion gerade?
Nicoguaro

Ja, es ist gerade
doetoe

Haben Sie versucht, Ihr Integral in eine ODE zu verwandeln?
Nicoguaro

1
Nein, Differenzierung nach und dann numerische Lösung der Differentialgleichung. x
Nicoguaro

1
Ihr erster Plot scheint eine andere Funktion zu zeigen als Ihr Integrand. Es scheint nämlich durch . Dh der Plot hat die Funktionλλxx(cos(λxcosx)sincx)
Ruslan

Antworten:


12

Verwenden Sie den Satz von Plancherel , um dieses Integral zu bewerten.

Die Grundidee ist, dass für zwei Funktionen ,f,g

I=f(x)g(x)dx=F(k)G(k)dk

wobei die Fourier-Transformationen von . Ihre Funktionen haben beide eine relativ geringe Unterstützung im Spektralbereich. Hier sollten und eine analytische Fourier-Transformation (oder Reihe) haben, wie die Jacobi-Anger-Erweiterung . Sie können die unendliche Reihe aufgrund des Zerfalls der Bessel-Funktion bei ungefähr Termenfür. Hoffe das hilft.F,Gf,gsinx/xrect(k)cos(λcosx)λ|Jn(x)|n>|x|

Bearbeiten : Eigentlich sollten Sie hier anstelle der Transformationen die Fourier-Reihen-Darstellungen verwenden. Der Transformationspfad führt zur Ableitung der bereits vorhandenen asymptotischen Darstellung (es stellt sich heraus, dass dies nur ). Der obige Satz von Plancherel funktioniert auch für Fourier-Reihen mit einer Integrationsdomäne von für das letzte Integral.πJ0(λ)[0,2π]


Danke, das ist eine sehr gute Idee!
Doetoe

7

Der Schlüssel zur Bewertung von Schwingungsintegralen besteht darin, das Integral am richtigen Punkt abzuschneiden. In diesem Beispiel müssen Sie die Obergrenze des Formulars auswählen. Bevor ich erkläre, warum es funktionieren sollte, möchte ich zunächst zeigen, dass es tatsächlich gute Ergebnisse liefert.

πN+π2

Asymptotika

Es ist leicht zu erraten, dass asymptotische Reihen die Form Um numerisch zu überprüfen, ob ist, reicht es aus, den Unterschied zwischen einem integralen und einem führenden asymptotischen Ausdruck zu zeichnen.

I(λ)2πλ[cos(λπ4)+c1sin(λπ4)λ+c2cos(λπ4)λ2+c3sin(λπ4)λ3+]
c1=18

int := NIntegrate[Cos[l*Cos[x]]*Sinc[x], {x, 0, 20.5*Pi}]; 
Plot[{l*(Sqrt[2*l/Pi]*int - Cos[l-Pi/4]), Sin[l-Pi/4]/8}, {l, Pi/4, 20}]

Als Ausgabe erhalten Sie einen schönen Sinus, der mit dem oben abgeleiteten übereinstimmt.

18

Wenn Sie die folgenden Koeffizienten finden möchten, müssen Sie bei Bedarf einen etwas komplexeren Code verwenden. Die Idee des folgenden Codes besteht darin, mehrere hoch liegende obere Grenzwerte zu verwenden und deren Ergebnisse zu "mitteln".

J[l_?NumericQ] := Block[{n=500},
  f[k_] := NIntegrate[Cos[l*Cos[x]]*Sinc[x], {x,0,(n+k)*Pi+Pi/2},
  Method->{"DoubleExponential"}, AccuracyGoal->14, MaxRecursion->100];
  1/2*((f[0]+f[1])/2+(f[1]+f[2])/2)
]
t = Table[{l, l^2*(Sqrt[2*l/Pi]*J[l] - Cos[l-Pi/4] - 1/8*Sin[l-Pi/4]/l)}, 
    {l, 4*Pi+Pi/4, 12*Pi+Pi/4, Pi/36}];
Fit[t, Table[Cos[l-Pi/4+Pi/2*n]/l^n, {n, 0, 10}], l]

Das ergibt die folgende Antwort.

c2=9128,c3=751024,c4=367532768,

Erläuterung

Einfaches Beispiel

Zur Veranschaulichung werde ich ein einfacheres Beispiel für das Sinusintegral Lassen Sie mich vorstellen, dass ich am Wert interessiert bin , aber ich weiß es nicht.

S(x)=0xsin(y)ydy.
S()=π2

Sinus

Sie sehen, dass um seinen Grenzwert schwingt, ähnlich wie Teilsummen des Wechsels in Vorzeichenreihen mit dem oberen Grenzwert schwingen. Wenn Sie eine solche Summe schätzen möchten, sollten Sie gemäß der Beschleunigungsmethode der Euler-Reihe Oder in Bezug auf die Sinus-Integral-Funktion sollten Sie sie bis zum Punkt zwischen maximaler und minimaler Schwingung integrieren. Wie aus der Darstellung klar ersichtlich ist, sind solche Punkte ungefähr gegeben durch für große Argumentwerte. Allgemeiner ist ein solcher Punkt derjenige, an demtritt ein.S(x)

SN=n=1N(1)nn.
SSN+12(1)N+1N+1.
S(x)0πN+π2sinxxdx
max|S(x)|

Ihr Problem

Wenn Sie aus Konstantins und Jaroslawiens Kurs auf das Integral zurückkommen, können Sie sehen, dass es sich genauso verhält wie der Sinus - Integral als Funktion der Obergrenze. Das heißt, Sie müssen nur die Werte berechnen. mit . Unten ist die Darstellung mehrerer solcher Werte mit .

Ix0(λ)=20x0cos(λcos(x))sinc(x)dx
x0=πN+π2λ=12π

tab = Table[{x0, 2*NIntegrate[Cos[12*Pi*Cos[x]]*Sinc[x], {x, 0, x0}, 
     Method->{"DoubleExponential"}, AccuracyGoal->12, MaxRecursion->100]},
    {x0, 10*Pi+Pi/2, 30*Pi+Pi/2, Pi}];
tab1 = Table[(tab[[i]] + tab[[i+1]])/2, {i,1,Length[tab]-1}];
ListPlot[{tab, tab1}]

gem

Hier sehen Sie das Ergebnis einer anderen Beschleunigungsmethode. Ich ordne Teilsummen folgendermaßen neu an: und eine neue Sequenz die viel schneller konvergiert. Dieser Trick ist auch nützlich, wenn Sie Integrale mit hoher Präzision bewerten möchten.

SN=12(SN+SN+1)
SN


Nett! Sind die Kursleiter Ihre echten Professoren? Ihr Kurs ist fantastisch, obwohl sehr hart und schnell
Doetoe

@doetoe ja, ich bin ein Schüler von Konstantin. Er hat mir einen Link zu Ihrer Frage mitgeteilt.
David Saykin

6

Oouras Methode für Fourier-Sinus-Integrale funktioniert hier, siehe:

Ooura, Takuya und Masatake Mori, Eine robuste Doppelexponentialformel für Integrale vom Fourier-Typ. Journal of Computational and Applied Mathematics 112.1-2 (1999): 229-241.

Ich habe eine Implementierung dieses Algorithmus geschrieben, aber nie die Arbeit investiert, um ihn schnell zu machen (z. B. durch Zwischenspeichern von Knoten / Gewichten), aber trotzdem erhalte ich konsistente Ergebnisse bei allem, was über die Float-Präzision hinausgeht:

float     = 0.0154244
double    = 0.943661538060268
long dbl  = 0.943661538066058702
quad      = 0.943661538066060288748574485677942
oct       = 0.943661538066060288748574485680878906503533004997613278231689169604876
asymptotic= 0.944029734

Hier ist der Code:

#include <iostream>
#include <boost/math/quadrature/ooura_fourier_integrals.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/float128.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>

template<class Real>
Real asymptotic(Real lambda) {
    using std::sin;
    using std::cos;
    using boost::math::constants::pi;
    Real I1 = cos(lambda - pi<Real>()/4)*sqrt(2*pi<Real>()/lambda);
    Real I2 = sin(lambda - pi<Real>()/4)*sqrt(2*pi<Real>()/(lambda*lambda*lambda))/8;
    return I1 + I2;
}

template<class Real>
Real osc(Real lambda) {
    using std::cos;
    using boost::math::quadrature::ooura_fourier_sin;
    auto f = [&lambda](Real x)->Real { return cos(lambda*cos(x))/x; };
    Real omega = 1;
    Real Is = ooura_fourier_sin<decltype(f), Real>(f, omega);
    return 2*Is;
}

template<class Real>
void print(Real val) {
   std::cout << std::defaultfloat;
   std::cout << std::setprecision(std::numeric_limits<Real>::digits10);
   std::cout <<  val <<  " = " << std::hexfloat << val;
}

int main() {
    using boost::multiprecision::float128;
    float128  s = 7;
    std::cout << "Asymptotic = " << std::setprecision(std::numeric_limits<float128>::digits10) << asymptotic(s) << "\n";
    std::cout << "float precision = ";
    print(osc(7.0f));
    std::cout << "\n";
    std::cout << "double precision= ";
    print(osc(7.0));
    std::cout << "\n";
    std::cout << "long double     = ";
    print(osc(7.0L));
    std::cout << "\n";
    print(osc(s));

    print(osc(boost::multiprecision::cpp_bin_float_oct(7)));
    std::cout << "\n";
}

Sie können den Unterschied zwischen der Quadratur und der Asymptotik nicht wirklich erkennen, da sie direkt übereinander liegen, außer als : λ0Geben Sie hier die Bildbeschreibung ein


Danke, das ist wirklich schön! Ich habe es noch nicht zum Laufen gebracht, meine Boost-Installation ist nicht kompatibel, aber ich lade jetzt die neueste Version herunter.
Doetoe

Nur um sicher zu gehen: In 23 haben Sie cos (Lambda * cos (x)) / x, ohne den Faktor sin (x) vom Integranden. Ist es ooura_fourier_sin, das diesen Faktor sin (x) annimmt, um den an ihn übergebenen Integranden zu multiplizieren?
Doetoe

Ich habe es zum Laufen gebracht. Es und seine Abhängigkeiten scheinen nur Header zu sein, so dass ich nicht einmal installieren oder kompilieren musste (mit Ausnahme der ausführbaren Datei). Ich hoffe es wird in Boost enthalten sein!
Doetoe

@doetoe: Ja, der Faktor ist implizit und wird in die Quadraturgewichte einbezogen. Ich denke darüber nach, es zu beschleunigen, indem ich es umgestalte, um die Knoten und Gewichte zwischenzuspeichern. wir werden sehen! sin(x)
user14717

@doetoe: Es ist in Boost 1.71 zusammengeführt. Die API unterscheidet sich ein wenig von dieser Antwort.
user14717
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.