J'ai besoin d'évaluer numériquement l'intégrale ci-dessous:
où , et . Ici est la fonction de Bessel modifiée du second type. Dans mon cas particulier, j'ai , etx∈R+λ,κ,ν>0Kλ=0,00313κ=0,00825ν=0,33 .
J'utilise MATLAB, et j'ai essayé les fonctions intégrées integral
et quadgk
, ce qui me donne beaucoup d'erreurs (voir ci-dessous). J'ai naturellement essayé de nombreuses autres choses aussi, comme l'intégration par parties et la sommation d'intégrales de à( k + 1 ) x π .
Alors, avez-vous des suggestions sur la méthode que je devrais essayer ensuite?
MISE À JOUR (questions ajoutées)
J'ai lu l'article @Pedro lié à, et je ne pense pas que ce soit trop difficile à comprendre. Cependant, j'ai quelques questions:
- Serait-il correct d'utiliser comme éléments de baseψ k , dans la méthode univariée de Levin décrite?
- Pourrais-je à la place simplement utiliser une méthode Filon, car la fréquence des oscillations est fixe?
Exemple de code
>> 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
la source
Réponses:
J'ai écrit mon propre intégrateur,
quadcc
qui s'adapte nettement mieux que les intégrateurs Matlab avec des singularités, et fournit une estimation d'erreur plus fiable.Pour l'utiliser pour votre problème, j'ai fait ce qui suit:
La fonction
f
est maintenant votre intégrale. Notez que je viens d'attribuer une ancienne valeur àx
.Afin de m'intégrer sur un domaine infini, j'applique une substitution de variables:
c'est-à-dire que l'intégration∞
g
de 0 à 1 devrait être la même chose que l'intégrationf
de 0 à . Différentes transformations peuvent produire des résultats de qualité différente: mathématiquement, toutes les transformations doivent donner le même résultat, mais des transformations différentes peuvent produire des s plus lisses ou plus facilement intégrables .g
J'appelle ensuite mon propre intégrateur,
quadcc
qui peut gérer lesNaN
s aux deux extrémités:Notez que l'estimation d'erreur est énorme, c'est
quadcc
-à- dire qu'elle n'a pas beaucoup confiance dans les résultats. En regardant la fonction, cependant, cela n'est pas surprenant car elle oscille à des valeurs de trois ordres de grandeur au-dessus de l'intégrale réelle. Encore une fois, l'utilisation d'une transformation d'intervalle différente peut produire de meilleurs résultats.Vous pouvez également envisager des méthodes plus spécifiques telles que celle-ci . C'est un peu plus compliqué, mais certainement la bonne méthode pour ce type de problème.
la source
integral
(1e-10 je pense), mais 1.7e + 07 est toujours vraiment, vraiment grande. Peut-être qu'une autre transformation fera du bien, comme vous le mentionnez.Comme le souligne Pedro, les méthodes de type Levin sont les méthodes les mieux établies pour ce type de problèmes.
Avez-vous accès à Mathematica? Pour ce problème, Mathematica les détectera et les utilisera par défaut:
Voici un tracé sur une plage de valeurs de x:
Vous pouvez également spécifier manuellement la méthode de type Levin particulière à appliquer, ce qui dans ce cas peut entraîner une légère amélioration des performances:
Voir la documentation pour plus de détails sur les méthodes de type Levin dans Mathematica .
la source
Si vous n'avez pas accès à Mathematica, vous pouvez écrire une méthode de type Levin (ou autre méthode oscillatoire spécialisée) dans Matlab comme le suggère Pedro.
Utilisez-vous la bibliothèque chebfun pour Matlab? Je viens d'apprendre qu'il contient une implémentation d'une méthode de base de type Levin ici . L'implémentation est écrite par Olver (l'un des experts du domaine de la quadrature oscillatoire). Il ne traite pas des singularités, de la subdivision adaptative, etc., mais il peut être juste ce dont vous avez besoin pour commencer.
la source
La transformation recommandée par Pedro est une excellente idée. Avez-vous essayé de jouer avec les paramètres de la fonction "quadgk" de Matlab? Par exemple, en utilisant la transformation de Pedro, vous pouvez faire ce qui suit:
quadgk(f, 0.0+eps, 1.0-eps, 'AbsTol', eps, 'MaxIntervalCount', 100000)
Utiliser cela me donne une solution de:
-2184689.50220729
et ne prend que 0,8 seconde (en utilisant les valeurs mentionnées ci-dessus: x = 10)
Walter Gander et Walter Gautschi ont un document sur la quadrature adaptative avec Matlab code que vous pouvez également utiliser (lien ici )
la source