วิธีการรวมเชิงตัวเลขของอินทิกรัลสโคปแบบยาก


25

ฉันจำเป็นต้องประเมินตัวเลขอินทิกรัลด้านล่าง:

0sinc(xr)rE(r)dr

ที่,xR+และλ,κ,ν>0 นี่Kคือฟังก์ชัน Bessel ที่แก้ไขของชนิดที่สอง ในกรณีของฉันโดยเฉพาะฉันมีλ=0.00313,κ=0.00825และν=0.33E(r)=r4(λκ2+r2)ν5/2Kν5/2(λκ2+r2)xR+λ,κ,ν>0Kλ=0.00313κ=0.00825ν=0.33 0.33

ฉันใช้ MATLAB และผมก็มีความพยายามในตัวฟังก์ชั่นintegralและquadgkซึ่งจะช่วยให้ฉันมากของข้อผิดพลาด (ดูด้านล่าง) ฉันได้พยายามธรรมชาติสิ่งอื่น ๆ อีกมากมายเช่นกันเช่นการบูรณาการโดยส่วนและข้อสรุปปริพันธ์จากไป( k + 1 ) x πkxπ(k+1)xπ

ดังนั้นคุณมีข้อเสนอแนะเกี่ยวกับวิธีที่ฉันควรลองต่อไปหรือไม่

UPDATE (คำถามเพิ่มเติม)
ฉันอ่านกระดาษ @Pedro ที่เชื่อมโยงกับและฉันไม่คิดว่ามันยากเกินไปที่จะเข้าใจ อย่างไรก็ตามฉันมีคำถามสองสามข้อ:

  • มันจะโอเคไหมที่จะใช้เป็นองค์ประกอบพื้นฐานψ kในวิธีของ univariate Levin ที่อธิบายไว้?xkψk
  • ฉันสามารถใช้วิธี Filon แทนได้หรือไม่เนื่องจากความถี่ของการแกว่งได้รับการแก้ไข

รหัสตัวอย่าง
>> 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


คืออะไรในหนึ่งของคุณหรือไม่ x
Pedro

จำนวนบวกใด ๆ ที่เป็นบวก ฉันเพิ่งอัพเดทโพสต์ของฉัน
torbonde

หากคุณสามารถแสดงรหัสและข้อผิดพลาดได้อาจไม่ใช่เรื่องยากที่จะแก้ไขส่วนใหญ่ แน่นอนโปรดลองอ่านข้อผิดพลาดอย่างรอบคอบก่อนและดูว่าคุณสามารถทำให้มันหายไปเองได้หรือไม่
Dennis Jaheruddin

ฉันจะแสดงความคิดเห็นในภายหลังวันนี้ด้วยรหัสและข้อผิดพลาดบางอย่าง หรือพรุ่งนี้
torbonde

โอเคฉันลืมไปแล้ว แต่ตอนนี้ฉันอัปเดตโพสต์ด้วยตัวอย่าง (ฉันแยกอินทิกรัลเป็นสองโดยการคำนวณอย่างชัดเจน) sinc
torbonde

คำตอบ:


12

ฉันเขียนผู้รวบรวมของฉันเองquadccซึ่งดีกว่าผู้รวบรวม Matlab ที่มีความเป็นเอกเทศอย่างมากและให้การประมาณการข้อผิดพลาดที่เชื่อถือได้มากขึ้น

เพื่อใช้สำหรับปัญหาของคุณฉันทำต่อไปนี้:

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

fตอนนี้ฟังก์ชั่นเป็น integrand ของคุณแล้ว หมายเหตุที่ผมได้รับมอบหมายเพียงค่าเก่า ๆ xไป

เพื่อที่จะรวมเข้ากับโดเมนที่ไม่มีที่สิ้นสุดฉันใช้การแทนที่ตัวแปร:

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

คือการบูรณาการg0-1 ควรจะเป็นเช่นเดียวกับการบูรณาการfจาก 0 ถึง∞การแปลงที่แตกต่างกันอาจให้ผลลัพธ์ที่มีคุณภาพแตกต่างกัน: ในทางคณิตศาสตร์การแปลงทั้งหมดควรให้ผลลัพธ์ที่เหมือนกัน แต่การแปลงที่ต่างกันอาจทำให้เกิดความราบรื่นหรือรวมกันได้ง่ายขึ้นgกว่า

จากนั้นฉันก็เรียกผู้รวบรวมของฉันเองquadccซึ่งสามารถจัดการกับNaNs ทั้งสองด้าน:

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

โปรดทราบว่าการประมาณการข้อผิดพลาดมีขนาดใหญ่มากเช่น quadccไม่มั่นใจในผลลัพธ์มากนัก ถึงแม้ว่าฟังก์ชั่นนี้จะไม่น่าแปลกใจเพราะมันสั่นค่าที่สามคำสั่งของขนาดที่สูงกว่าอินทิกรัลจริง อีกครั้งการใช้การแปลงช่วงเวลาที่แตกต่างกันอาจให้ผลลัพธ์ที่ดีกว่า

นอกจากนี้คุณยังอาจต้องการที่จะดูที่วิธีการเฉพาะเจาะจงมากขึ้นเช่นนี้ มันเกี่ยวข้องกับอีกเล็กน้อย แต่เป็นวิธีที่เหมาะสมสำหรับปัญหาประเภทนี้


ขอบคุณมาก. ฉันจะดูวิธีการต่าง ๆ สำหรับวัตถุประสงค์ของฉันข้อผิดพลาดไม่จำเป็นต้องมีขนาดเล็กเท่ากับมาตรฐานใน eq integral(1e-10 ฉันคิดว่า) แต่ 1.7e + 07 ยังคงมีขนาดใหญ่มาก บางทีการเปลี่ยนรูปแบบอื่นอาจทำได้ดีดังที่คุณพูดถึง
torbonde

@ cimrg.joe: โปรดทราบว่าการประมาณข้อผิดพลาดเป็นการประมาณค่าของข้อผิดพลาดแบบสัมบูรณ์โดยอ้างอิงจากค่าสัมบูรณ์สูงสุดของ integrand ในบางกรณีค่าที่ส่งคืนอาจจะค่อนข้างโอเค หากคุณกำลังมองหาความแม่นยำสิบหลักฉันขอแนะนำให้ใช้วิธีการแบบเลวินที่ฉันพูดถึงในตอนท้ายของโพสต์
Pedro

ฉันอาจไม่ต้องการความแม่นยำสิบหลัก แต่ฉันคิดว่าฉันต้องการอย่างน้อยห้า วิธีการของคุณสามารถผลิตได้หรือไม่
torbonde

วิธีการไม่สามารถรับประกันความแม่นยำแบบนั้นสำหรับอินทิกรัลของคุณได้เนื่องจากค่าที่ด้านขวาสุดของช่วงเวลานั้นมีขนาดของคำสั่งที่ใหญ่กว่าอินทิกรัลเอง
Pedro

11

ดังที่โดรส์ชี้ให้เห็นว่าวิธีการของเลวินเป็นวิธีที่ดีที่สุดสำหรับปัญหาประเภทนี้

คุณมีสิทธิ์เข้าถึง Mathematica หรือไม่? สำหรับปัญหานี้ Mathematica จะตรวจจับและใช้พวกมันตามค่าเริ่มต้น:

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.

นี่คือพล็อตในช่วงของค่า x:

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

แปลงจาก x = 0.5 ถึง x = 10

นอกจากนี้คุณยังสามารถระบุวิธีการเฉพาะของ Levin ที่จะใช้ด้วยตนเองซึ่งในกรณีนี้สามารถเพิ่มประสิทธิภาพได้เล็กน้อย:

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.

โปรดดูเอกสารสำหรับรายละเอียดของวิธีการ Levin ชนิดใน Mathematica


น่าเสียดายที่ฉันไม่มีสิทธิ์เข้าถึง Mathematica - เพียง MATLAB ฉันเพิ่งจะอัปเดตคำถามของฉันเมื่อมีคำถามเพิ่มเติมบางส่วนเกี่ยวกับกระดาษ @Pedro ที่เชื่อมโยงกับ
torbonde

ตกลงอย่างที่คุณบอกว่าคุณต้องทำกับ Matlab ฉันจะเพิ่มอีกคำตอบเกี่ยวกับที่
Andrew Moylan

5

หากคุณไม่มีสิทธิ์เข้าถึง Mathematica คุณสามารถเขียนวิธี Levin-type (หรือ oscillatory แบบพิเศษ) ใน Matlab ตามที่ Pedro แนะนำ

คุณใช้chebfun library สำหรับ Matlab หรือไม่? ฉันเพียงแค่เรียนรู้ที่จะมีการดำเนินการตามวิธีการที่เลวินชนิดพื้นฐานที่นี่ การดำเนินการถูกเขียนขึ้นโดย Olver (หนึ่งในผู้เชี่ยวชาญในสาขาการสร้างพื้นที่สี่เหลี่ยมจัตุรัส) มันไม่ได้เกี่ยวข้องกับความแปลกแยกการปรับตัว ฯลฯ แต่มันอาจเป็นเพียงสิ่งที่คุณต้องเริ่มต้น


ฉันคิดเกี่ยวกับการใช้วิธีการของเลวินด้วยตัวเอง แต่ฉันไม่แน่ใจว่าฉันพร้อมสำหรับความท้าทายหรือยัง ฉันคิดว่าฉันต้องเข้าใจวิธีการที่ดีขึ้นเล็กน้อย บางทีฉันอาจพูดคุยกับที่ปรึกษาของฉันเกี่ยวกับเรื่องนี้ อย่างไรก็ตามเหตุผลที่ฉันถามเกี่ยวกับวิธีการ Filon ก็คือพวกเขาดูเหมือนจะง่ายต่อการใช้ และเนื่องจากฉันไม่ต้องการความแม่นยำสูงมาก แต่นี่เป็นส่วนหนึ่งของวิทยานิพนธ์หลักของฉันความยากลำบากมีน้ำหนัก
torbonde

ฉันได้ดูห้องสมุด chebfun (ซึ่งน่าประทับใจ) และตัวอย่างการรวมระบบของเลวิน แต่ฉันไม่สามารถทำงานได้ ฉันได้โพสต์คำถามเกี่ยวกับที่นี่จริง ๆ
torbonde

0

การเปลี่ยนแปลงที่แนะนำโดยเปโดรเป็นความคิดที่ดี คุณได้ลองใช้พารามิเตอร์ในฟังก์ชั่น "quadgk" ของ Matlab แล้วหรือยัง? ตัวอย่างเช่นการใช้การแปลงของ Pedro คุณสามารถทำสิ่งต่อไปนี้:
quadgk(f, 0.0+eps, 1.0-eps, 'AbsTol', eps, 'MaxIntervalCount', 100000)
การใช้สิ่งนี้ทำให้ฉันได้รับ:
-2184689.50220729
และใช้เวลาเพียง 0.8 วินาทีเท่านั้น (โดยใช้ค่าที่กล่าวถึงข้างต้น: x = 10)
Walter Gander และ Walter Gautschi มีกระดาษ รหัสที่คุณสามารถใช้ได้เช่นกัน (ลิงค์ที่นี่ )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.