Método para integração numérica da integral oscilatória difícil


25

Preciso avaliar numericamente a integral abaixo:

∫0∞sinc′(xr)rE(r)dr

onde , e . Aqui é a função de Bessel modificada do segundo tipo. No meu caso particular, tenho , e .x∈R+λ,κ,ν>0Kλ=0,00313κ=0,00825ν=0,33E(r)=r4(λκ2+r2)−ν−5/2K−ν−5/2(λκ2+r2)x∈R+λ,κ,ν>0Kλ=0.00313κ=0.00825ν=0.33

Estou usando o MATLAB e tentei as funções internas integrale quadgk, o que me deu muitos erros (veja abaixo). Naturalmente, tentei várias outras coisas, como integrar por partes e somar integrais de a .( k + 1 ) x πkxπ(k+1)xπ

Então, você tem alguma sugestão sobre qual método devo tentar a seguir?

ATUALIZAÇÃO (perguntas adicionadas)
Li o artigo @Pedro vinculado e não acho que seja muito difícil de entender. No entanto, tenho algumas perguntas:

  • Seria bom usar como os elementos base , no método univariado de Levin descrito?ψ kxkψk
  • Em vez disso, eu poderia apenas usar um método Filon, já que a frequência das oscilações é fixa?

Código de exemplo
>> 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


O que é na sua integral? x
— Pedro

Qualquer número positivo e real. Acabei de atualizar minha postagem.
— torbonde

Se você puder mostrar algum código e erros, provavelmente não será muito difícil resolver a maioria deles. Obviamente, tente ler o erro cuidadosamente primeiro e veja se você pode desaparecer por conta própria.
— Dennis Jaheruddin

Farei um comentário ainda hoje com alguns códigos e erros. Ou amanhã.
— precisa saber é o seguinte

Ok, então eu esqueci. Mas agora atualizei minha postagem com um exemplo (dividi a integral em duas calculando explicitamente). sinc′
— torbonde

Respostas:


12

Eu escrevi meu próprio integrador, quadccque lida substancialmente melhor do que os integradores Matlab com singularidades e fornece uma estimativa de erro mais confiável.

Para usá-lo para o seu problema, fiz o seguinte:

>> 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) );

A função fagora é seu integrando. Observe que eu acabei de atribuir qualquer valor antigo a x.

Para integrar em um domínio infinito, aplico uma substituição de variáveis:

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

isto é, integrar gde 0 a 1 deve ser o mesmo que integrar fde 0 a . Transformações diferentes podem produzir resultados de qualidade diferentes: matematicamente todas as transformações devem fornecer o mesmo resultado, mas transformações diferentes podem produzir s mais suaves ou mais facilmente integráveis .∞g

Então chamo meu próprio integrador, quadccque pode lidar com os NaNdois lados:

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

Observe que a estimativa de erro é enorme, ou seja quadcc, não tem muita confiança nos resultados. Olhando para a função, porém, isso não é surpreendente, pois oscila em valores três ordens de grandeza acima da integral real. Novamente, o uso de uma transformação de intervalo diferente pode produzir melhores resultados.

Você também pode querer procurar métodos mais específicos como esse . É um pouco mais envolvido, mas definitivamente o método certo para esse tipo de problema.


Muito obrigado. Vou dar uma olhada nos diferentes métodos. Para meus propósitos, o erro não precisa ser tão pequeno quanto o padrão na eq integral(1e-10 eu acho), mas 1,7e + 07 ainda é muito, muito grande. Talvez outra transformação faça o bem, como você mencionou.
— torbonde

@ cimrg.joe: Observe que a estimativa de erro é uma estimativa do erro absoluto com base, entre outros, nos valores absolutos máximos do integrando. Em alguns casos extremos, o valor retornado pode realmente estar bem. Se você está procurando dez dígitos de precisão, é altamente recomendável usar os métodos do tipo Levin que mencionei no final da minha postagem.
— Pedro

Talvez eu não precise de dez dígitos de precisão, mas acho que preciso de pelo menos cinco. Seu método pode produzir isso?
— torbonde

O método não pode garantir esse tipo de precisão para sua integral, uma vez que os valores na extremidade direita do intervalo são várias ordens de magnitude maiores que a própria integral.
— Pedro

11

Como aponta Pedro, os métodos do tipo Levin são os melhores métodos estabelecidos para esse tipo de problema.

Você tem acesso ao Mathematica? Para esse problema, o Mathematica irá detectá-los e usá-los por padrão:

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.

Aqui está um gráfico sobre uma faixa de valores de x:

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

Traçar de x = 0,5 ex = 10

Você também pode especificar manualmente o método do tipo Levin específico a ser aplicado, que nesse caso pode resultar em uma ligeira melhoria no desempenho:

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.

Consulte a documentação para obter detalhes dos métodos do tipo Levin no Mathematica .


Infelizmente não tenho acesso ao Mathematica - apenas ao MATLAB. Vou atualizar minha pergunta com algumas perguntas adicionais, relacionadas ao artigo @Pedro vinculado.
— torbonde

OK, como você diz, terá que se contentar com o Matlab. Vou acrescentar outra resposta sobre isso.
— Andrew Moylan

5

Se você não tem acesso ao Mathematica, você pode escrever um método do tipo Levin (ou outro oscilador especializado) no Matlab, como Pedro sugere.

Você usa a biblioteca chebfun para o Matlab? Acabei de aprender que ele contém uma implementação de um método básico do tipo Levin aqui . A implementação foi escrita por Olver (um dos especialistas no campo da quadratura oscilatória). Não lida com singularidades, subdivisões adaptativas, etc., mas pode ser exatamente o que você precisa para começar.


Pensei em implementar um método Levin, mas ainda não tenho certeza se estou pronto para o desafio. Eu acho que preciso entender o método um pouco melhor. Talvez eu possa falar com meu consultor sobre isso. Enfim, o motivo que perguntei sobre os métodos Filon é que eles parecem mais fáceis de implementar. E desde que eu não preciso de precisão extremamente elevada, mas isso é parte da minha tese de mestrado, dificuldade pesa.
— torbonde

Eu dei uma olhada na biblioteca chebfun (que é impressionante) e no exemplo de integração Levin. Mas não consigo fazê-lo funcionar. Na verdade, eu postei uma pergunta sobre isso aqui .
— torbonde

0

A transformação recomendada por Pedro é uma ótima idéia. Você tentou brincar com os parâmetros da função "quadgk" do Matlab? Por exemplo, usando a transformação de Pedro, você pode fazer o seguinte:
quadgk(f, 0.0+eps, 1.0-eps, 'AbsTol', eps, 'MaxIntervalCount', 100000)
Usar isso fornece uma solução de:
-2184689.50220729
e leva apenas 0,8 segundos (usando os valores mencionados acima: x = 10)
Walter Gander e Walter Gautschi têm um artigo sobre quadratura adaptativa com o Matlab código que você pode usar também (link aqui )

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.