Metodo per l'integrazione numerica dell'integrale oscillatorio difficile


25

Devo valutare numericamente l'integrale di seguito:

0sinc(xr)rE(r)dr

dove ,xR+eλ,κ,ν>0. QuiKè la funzione di Bessel modificata del secondo tipo. Nel mio caso particolare hoλ=0,00313,κ=0,00825eν=0,33.E(r)=r4(λκ2+r2)ν5/2Kν5/2(λκ2+r2)xR+λ,κ,ν>0Kλ=0,00,313 milaκ=0,00,825 milaν=0,33

Sto usando MATLAB e ho provato le funzioni integrate integrale quadgk, il che mi dà molti errori (vedi sotto). Ho naturalmente provato anche molte altre cose, come l'integrazione per parti e la somma degli integrali da a ( k + 1 ) x π .KXπ(K+1)Xπ

Quindi, hai qualche suggerimento su quale metodo dovrei provare dopo?

AGGIORNAMENTO (domande aggiunte)
Ho letto l'articolo a cui @Pedro è collegato e non credo che sia stato troppo difficile da capire. Tuttavia, ho alcune domande:

  • Andrebbe bene usare come elementi base ψ k , nel metodo univariato di Levin descritto?XKψK
  • Potrei invece usare solo un metodo Filon, poiché la frequenza delle oscillazioni è fissa?

Codice di esempio
>> integral(@(r) sin(x*r).*sqrt(E(r)),0,Inf)
Warning: Reached the limit on the maximum number of intervals in use. Approximate
bound on error is 1.6e+07. The integral may not exist, or it may be difficult to
approximate numerically to the requested accuracy.
> In funfun\private\integralCalc>iterateScalarValued at 372
In funfun\private\integralCalc>vadapt at 133
In funfun\private\integralCalc at 84
In integral at 89

ans =

3.3197e+06


Che cos'è nel tuo integrale? X
Pedro

Qualsiasi numero positivo e reale. Ho appena aggiornato il mio post.
torbonde,

Se potessi mostrare del codice e degli errori, probabilmente non è troppo difficile risolverli. Ovviamente prova prima a leggere attentamente l'errore e vedi se riesci a farlo sparire da solo.
Dennis Jaheruddin,

Farò un commento più tardi oggi con un po 'di codice ed errori. O domani.
torbonde,

Va bene, quindi ho dimenticato. Ma ora ho aggiornato il mio post con un esempio (ho diviso l'integrale in due calcolando esplicitamente ). Sionc'
torbonde,

Risposte:


12

Ho scritto il mio integratore, quadccche è sostanzialmente migliore degli integratori Matlab con le singolarità e fornisce una stima dell'errore più affidabile.

Per usarlo per il tuo problema, ho fatto quanto segue:

>> lambda = 0.00313; kappa = 0.00825; nu = 0.33;
>> x = 10;
>> E = @(r) r.^4.*(lambda*sqrt(kappa^2 + r.^2)).^(-nu-5/2) .* besselk(-nu-5/2,lambda*sqrt(kappa^2 + r.^2));
>> sincp = @(x) cos(x)./x - sin(x)./x.^2;
>> f = @(r) sincp(x*r) .* r .* sqrt( E(r) );

La funzione fè ora il tuo integrando. Nota che ho appena assegnato un valore precedente a x.

Per integrarmi in un dominio infinito, applico una sostituzione di variabili:

>> g = @(x) f ( tan ( pi / 2 * x ) ) .* ( 1 + tan ( pi * x / 2 ).^2 ) * pi / 2;

ovvero l'integrazione gda 0 a 1 dovrebbe essere uguale all'integrazione fda 0 a . Diverse trasformazioni possono produrre risultati di qualità diversa: matematicamente tutte le trasformazioni dovrebbero dare lo stesso risultato, ma trasformazioni diverse possono produrre s più fluidi o più facilmente integrabili .g

Chiamo quindi il mio integratore, quadccche può gestire i messaggi di posta NaNelettronica su entrambi i lati:

>> [ int , err , npoints ] = quadcc( g , 0 , 1 , 1e-6 )
int =
  -1.9552e+06
err =
   1.6933e+07
npoints =
       20761

Si noti che la stima dell'errore è enorme, cioè quadccnon ha molta fiducia nei risultati. Osservando la funzione, tuttavia, ciò non sorprende poiché oscilla a valori di tre ordini di grandezza al di sopra dell'integrale reale. Ancora una volta, l'utilizzo di una trasformazione di intervallo diversa può produrre risultati migliori.

Potresti anche voler esaminare metodi più specifici come questo . È un po 'più coinvolto, ma sicuramente il metodo giusto per questo tipo di problema.


Grazie mille. Vedrò i diversi metodi. Per i miei scopi, l'errore non deve essere piccolo come lo è standard in eq integral(1e-10 penso), ma 1.7e + 07 è ancora molto, molto grande. Forse un'altra trasformazione farà del bene, come dici tu.
torbonde,

@ cimrg.joe: la stima dell'errore è una stima dell'errore assoluto basata, tra l'altro, sui valori assoluti massimi dell'integrando. In alcuni casi estremi, il valore restituito potrebbe effettivamente essere abbastanza ok. Se stai cercando dieci cifre di precisione, ti consiglio vivamente di utilizzare i metodi di tipo Levin che ho citato alla fine del mio post.
Pedro

Forse non ho bisogno di dieci cifre di precisione, ma penso di averne bisogno almeno cinque. Il tuo metodo può produrlo?
torbonde,

Il metodo non può garantire quel tipo di precisione per il tuo integrale poiché i valori all'estremità destra dell'intervallo sono diversi ordini di grandezza più grandi dell'integrale stesso.
Pedro,

11

Come sottolinea Pedro, i metodi di tipo Levin sono i metodi meglio stabiliti per questo tipo di problemi.

Hai accesso a Mathematica? Per questo problema, Mathematica li rileverà e li userà per impostazione predefinita:

In[1]:= e[r_] := 
 r^4 (l Sqrt[k^2 + r^2])^(-v - 5/2) BesselK[-v - 5/2, l Sqrt[k^2 + r^2]]

In[2]:= {l, k, v} = {0.00313, 0.00825, 0.33};

In[3]:= Block[{x = 10}, 
 NIntegrate[Sinc'[x r] r Sqrt[e[r]], {r, 0, \[Infinity]}, 
  PrecisionGoal -> 3]]

Out[3]= -112494.

Ecco un grafico su un intervallo di valori di x:

In[4]:= ListLinePlot[
 Table[NIntegrate[Sinc'[x r] r Sqrt[e[r]], {r, 0, \[Infinity]}, 
   PrecisionGoal -> 3], {x, .5, 10, 0.1}]]

Traccia da x = 0,5 a x = 10

Puoi anche specificare manualmente il particolare metodo di tipo Levin da applicare, che in questo caso può produrre un leggero miglioramento delle prestazioni:

In[5]:= method = {"LevinRule", "Kernel" -> {Cos[r x], Sin[r x]}, 
   "DifferentialMatrix" -> {{0, -x}, {x, 0}}, 
   "Amplitude" -> {(
     3497.878840962873` Sqrt[(
      r^4 BesselK[-2.17`, 
        0.00313` Sqrt[
         0.00006806250000000001` + r^2]])/(0.00006806250000000001` + 
        r^2)^1.415`])/
     x, -((3497.878840962873` Sqrt[(
       r^4 BesselK[-2.17`, 
         0.00313` Sqrt[
          0.00006806250000000001` + r^2]])/(0.00006806250000000001` + 
         r^2)^1.415`])/(r x^2))}, "AdditiveTerm" -> 0};

In[6]:= Block[{x = 10}, 
 NIntegrate[Sinc'[x r] r Sqrt[e[r]], {r, 0, \[Infinity]}, 
  PrecisionGoal -> 3, Method -> method]]

Out[6]= -112495.

Consultare la documentazione per i dettagli sui metodi di tipo Levin in Mathematica .


Sfortunatamente non ho accesso a Mathematica - solo MATLAB. Aggiornerò la mia domanda con alcune domande aggiuntive, riguardanti il ​​documento a cui @Pedro è collegato.
torbonde,

OK, come dici tu dovrai accontentarti di Matlab. Aggiungerò un'altra risposta a riguardo.
Andrew Moylan,

5

Se non hai accesso a Mathematica, potresti scrivere un metodo di tipo Levin (o altro metodo oscillatorio specializzato) in Matlab come suggerisce Pedro.

Usi la libreria chebfun per Matlab? Ho appena imparato che contiene un'implementazione di un metodo di base di tipo Levin qui . L'implementazione è scritta da Olver (uno degli esperti nel campo della quadratura oscillatoria). Non si tratta di singolarità, suddivisione adattativa ecc., Ma potrebbe essere proprio quello che ti serve per iniziare.


Ho pensato di implementare un metodo Levin da solo, ma non sono sicuro di essere pronto per la sfida. Penso di dover capire un po 'meglio il metodo. Forse potrei parlarne con il mio consulente. Comunque, il motivo per cui ho chiesto dei metodi Filon è che sembrano più facili da implementare. E poiché non ho bisogno di una precisione estremamente elevata, ma questo fa parte della mia tesi di laurea, la difficoltà pesa.
torbonde

Ho dato un'occhiata alla libreria chebfun (che è impressionante) e all'esempio di integrazione di Levin. Ma non riesco a farlo funzionare. Ho effettivamente pubblicato una domanda al riguardo qui .
torbonde,

0

La trasformazione raccomandata da Pedro è un'ottima idea. Hai provato a giocare con i parametri nella funzione "quadgk" di Matlab? Ad esempio, usando la trasformazione di Pedro, puoi fare quanto segue:
quadgk(f, 0.0+eps, 1.0-eps, 'AbsTol', eps, 'MaxIntervalCount', 100000)
Usare questo mi dà una soluzione di:
-2184689.50220729
e richiede solo 0,8 secondi (usando i valori sopra menzionati: x = 10)
Walter Gander e Walter Gautschi hanno un documento sulla quadratura adattiva con Matlab codice che puoi usare anche (link qui )

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.