लाप्लास समीकरण को हल करें


13

संख्यात्मक गणित का परिचय

यह "हैलो, वर्ल्ड!" पीडीई के (आंशिक अंतर समीकरण)। द लैप्लस या डिफ्यूजन इक्वेशन भौतिकी में अक्सर दिखाई देता है, उदाहरण के लिए हीट इक्वेशन, डीफॉर्मिंग, फ्लूड डायनामिक्स आदि ... जैसा कि वास्तविक जीवन 3 डी है, लेकिन हम "हैलो, वर्ल्ड!" कहना चाहते हैं। और "99 बोतल बीयर, ..." नहीं गाएं, यह कार्य 1 डी में दिया गया है। आप इसकी व्याख्या कर सकते हैं कि रबर के बागे को दीवार पर बांधकर दोनों छोरों पर लगाया जाता है।

किसी [0,1]डोमेन पर uदिए गए स्रोत फ़ंक्शन fऔर सीमा मानों u_Lऔर u_Rइस तरह के लिए एक फ़ंक्शन खोजें :

  • -u'' = f
  • u(0) = u_L
  • u(1) = u_R

u'' के दूसरे व्युत्पन्न को दर्शाता है u

इसे विशुद्ध रूप से सैद्धांतिक रूप से हल किया जा सकता है, लेकिन आपका काम यह है कि इसे अंकों के लिए एक विवेकपूर्ण डोमेन x पर संख्यात्मक रूप से हल करें N:

  • x = {i/(N-1) | i=0..N-1}या 1-आधारित:{(i-1)/(N-1) | i=1..N}
  • h = 1/(N-1) रिक्ति है

इनपुट

  • f फ़ंक्शन या अभिव्यक्ति या स्ट्रिंग के रूप में
  • u_L, u_Rअस्थायी बिंदु मानों के रूप में
  • N पूर्णांक के रूप में> = 2

उत्पादन

  • सरणी, सूची, कुछ अलग प्रकार की स्ट्रिंग है uकिu_i == u(x_i)

उदाहरण

उदाहरण 1

इनपुट: f = -2, u_L = u_R = 0, N = 10(क्या नहीं ले f=-2गलत है, है न एक मूल्य लेकिन एक निरंतर समारोह है कि रिटर्न है -2सभी के लिए x। यह हमारी रस्सी पर एक निरंतर गुरुत्वाकर्षण बल की तरह है।)

आउटपुट: [-0.0, -0.09876543209876543, -0.1728395061728395, -0.22222222222222224, -0.24691358024691357, -0.24691358024691357, -0.22222222222222224, -0.1728395061728395, -0.09876543209876547, -0.0]

एक आसान सटीक समाधान मौजूद है: u = -x*(1-x)

उदाहरण 2

इनपुट: f = 10*x, u_L = 0 u_R = 1, N = 15(यहाँ वहाँ सही पक्ष पर हवा आने की दिशा का एक बहुत है)

आउटपुट: [ 0., 0.1898688, 0.37609329, 0.55502915, 0.72303207, 0.87645773, 1.01166181, 1.125, 1.21282799, 1.27150146, 1.29737609, 1.28680758, 1.2361516, 1.14176385, 1.]

इस स्थिति का सटीक समाधान: u = 1/3*(8*x-5*x^3)

उदाहरण 3

इनपुट: f = sin(2*pi*x), u_L = u_R = 1, N = 20(किसी व्यक्ति ने गुरुत्वाकर्षण तोड़ दिया या वहाँ उर्ध्वप्रवाह और हवा के साथ एक तरह से है)

आउटपुट: [ 1., 1.0083001, 1.01570075, 1.02139999, 1.0247802, 1.0254751, 1.02340937, 1.01880687, 1.01216636, 1.00420743, 0.99579257, 0.98783364, 0.98119313, 0.97659063, 0.9745249, 0.9752198, 0.97860001, 0.98429925, 0.9916999, 1.]

यहाँ सटीक समाधान है u = (sin(2*π*x))/(4*π^2)+1

उदाहरण 4

इनपुट: f = exp(x^2), u_L = u_R = 0,N=30

आउटपुट: [ 0. 0.02021032 0.03923016 0.05705528 0.07367854 0.0890899 0.10327633 0.11622169 0.12790665 0.13830853 0.14740113 0.15515453 0.16153488 0.1665041 0.17001962 0.172034 0.17249459 0.17134303 0.16851482 0.1639387 0.15753606 0.1492202 0.13889553 0.12645668 0.11178744 0.09475961 0.07523169 0.05304738 0.02803389 0. ]

मामूली विषमता पर ध्यान दें

FDM

इसे हल करने की एक संभावित विधि परिमित अंतर विधि है :

  • के -u_i'' = f_iरूप में फिर से लिखना
  • (-u_{i-1} + 2u_i - u{i+1})/h² = f_i जो बराबर है
  • -u_{i-1} + 2u_i - u{i+1} = h²f_i
  • समीकरण सेट करें:

  • जो मैट्रिक्स-वेक्टर समीकरण के बराबर हैं:

  • इस समीकरण को हल करें और आउटपुट करें u_i

पायथन में प्रदर्शन के लिए इसका एक कार्यान्वयन:

import matplotlib.pyplot as plt
import numpy as np
def laplace(f, uL, uR, N):
 h = 1./(N-1)
 x = [i*h for i in range(N)]

 A = np.zeros((N,N))
 b = np.zeros((N,))

 A[0,0] = 1
 b[0] = uL

 for i in range(1,N-1):
  A[i,i-1] = -1
  A[i,i]   =  2
  A[i,i+1] = -1
  b[i]     = h**2*f(x[i])

 A[N-1,N-1] = 1
 b[N-1]     = uR

 u = np.linalg.solve(A,b)

 plt.plot(x,u,'*-')
 plt.show()

 return u

print laplace(lambda x:-2, 0, 0, 10)
print laplace(lambda x:10*x, 0, 1, 15)
print laplace(lambda x:np.sin(2*np.pi*x), 1, 1, 20)

मैट्रिक्स बीजगणित के बिना वैकल्पिक कार्यान्वयन ( जैकोबी विधि का उपयोग करके )

def laplace(f, uL, uR, N):
 h=1./(N-1)
 b=[f(i*h)*h*h for i in range(N)]
 b[0],b[-1]=uL,uR
 u = [0]*N

 def residual():
  return np.sqrt(sum(r*r for r in[b[i] + u[i-1] - 2*u[i] + u[i+1] for i in range(1,N-1)]))

 def jacobi():
  return [uL] + [0.5*(b[i] + u[i-1] + u[i+1]) for i in range(1,N-1)] + [uR]

 while residual() > 1e-6:
  u = jacobi()

 return u

हालाँकि आप लाप्लास समीकरण को हल करने के लिए किसी अन्य विधि का उपयोग कर सकते हैं। यदि आप एक पुनरावृत्त विधि का उपयोग करते हैं, तो आपको दाहिने हाथ की ओर वेक्टर होने के |b-Au|<1e-6साथ, अवशिष्ट तक पुनरावृति करना चाहिएbu_L,f_1h²,f_2h²,...

टिप्पणियाँ

आपकी समाधान पद्धति के आधार पर आप दिए गए समाधानों के लिए उदाहरणों का समाधान नहीं कर सकते हैं। कम से कम N->infinityत्रुटि के लिए शून्य से संपर्क करना चाहिए।

मानक खामियों को अस्वीकार कर दिया जाता है , पीडीई के लिए बिल्ट-इन की अनुमति है।

बक्शीश

समाधान को प्रदर्शित करने के लिए -30% का बोनस, या तो ग्राफिकल या एएससीआईआई-कला।

जीतना

यह कोडगुल्फ़ है, इसलिए बाइट्स जीत में सबसे छोटा कोड है!


मैं एक उदाहरण जोड़ने की सलाह देता हूं जो विश्लेषणात्मक रूप से हल करने योग्य नहीं है, उदाहरण के लिए f(x) = exp(x^2)
निर्दोष

@flawr ज़रूर, इसमें एक समाधान है लेकिन त्रुटि फ़ंक्शन शामिल है।
कार्ल नेफ

1
क्षमा करें, यह शायद गलत अभिव्यक्ति थी, "गैर-प्राथमिक विरोधी" बेहतर हो सकता है? मेरा मतलब है कि फ़ंक्शंस जैसे कि log(log(x))या sqrt(1-x^4)जिसमें एक अभिन्न है, जो कि प्राथमिक कार्यों में व्यक्त नहीं है।
निर्दोष

@flawr नहीं यह ठीक है, त्रुटि फ़ंक्शन प्राथमिक नहीं है, मैं सिर्फ यह कहना चाहता था कि समाधान को व्यक्त करने का एक तरीका है, लेकिन u(x) = 1/2 (-sqrt(π) x erfi(x)+sqrt(π) erfi(1) x+e^(x^2)-e x+x-1)यह बिल्कुल गणना योग्य नहीं है।
कार्ल नेफ

क्यों 1e-6 तक पुनरावृति और 1e-30 तक पुनरावृति नहीं?
रोजलूपी

जवाबों:


4

गणितज्ञ, 52.5 बाइट्स (= 75 * (1 - 30%))

+0.7 बाइट्स प्रति @flawr की टिप्पणी।

ListPlot[{#,u@#}&/@Subdivide@#4/.NDSolve[-u''@x==#&&u@0==#2&&u@1==#3,u,x]]&

यह आउटपुट प्लॉट करता है।

जैसे

ListPlot[ ... ]&[10 x, 0, 1, 15]

यहाँ छवि विवरण दर्ज करें

व्याख्या

NDSolve[-u''@x==#&&u@0==#2&&u@1==#3,u,x]

फ़ंक्शन के लिए हल करें u

Subdivide@#4

Subdivide अंतराल [0,1] एन (4 वें इनपुट) भागों में।

{#,u@#}&/@ ...

uके आउटपुट में मैप करें Subdivide

ListPlot[ ... ]

अंतिम परिणाम प्लॉट करें।

गैर-रेखांकन समाधान: 58 बाइट्स

u/@Subdivide@#4/.NDSolve[-u''@x==#&&u@0==#2&&u@1==#3,u,x]&

यह काम नहीं करता हैf(x) = exp(x^2)
9

शायद आप NDSolveगैर प्राथमिक समाधान के सामान्य मामले के लिए उपयोग करना चाहते हैं।
10

6

मतलाब, 84, 81.2 79.1 बाइट्स = 113 - 30%

function u=l(f,N,a,b);A=toeplitz([2,-1,(3:N)*0]);A([1,2,end-[1,0]])=eye(2);u=[a,f((1:N-2)/N)*(N-1)^2,b]/A;plot(u)

ध्यान दें कि इस उदाहरण में मैं पंक्ति वैक्टर का उपयोग करता हूं, इसका मतलब है कि मैट्रिक्स Aट्रांसपोज़्ड है। fएक समारोह संभाल के रूप में लिया जाता है, a,bबाएँ / दाएँ पक्ष Dirichlet contraints हैं।

function u=l(f,N,a,b);
A=toeplitz([2,-1,(3:N)*0]);       % use the "toeplitz" builtin to generate the matrix
A([1,2,end-[1,0]])=eye(2);        % adjust first and last column of matrix
u=[a,f((1:N-2)/N)*(N-1)^2,b]/A;   % build right hand side (as row vector) and right mu
plot(u)                           % plot the solution

उदाहरण के लिए f = 10*x, u_L = 0 u_R = 1, N = 15इस परिणाम में:


3

आर, 123.2 102.9 98.7 बाइट्स (141-30%)

संपादित करें: @Angs के लिए मुट्ठी भर बाइट्स सहेजे गए!

अगर कोई ऐसा करने के लिए स्वतंत्र महसूस करता है तो चित्रों को संपादित करना चाहता है। यह मूल रूप से पोस्ट किए गए मैटलैब और पायथन दोनों संस्करणों का एक आर रूपांतरण है।

function(f,a,b,N){n=N-1;x=1:N/n;A=toeplitz(c(2,-1,rep(0,N-2)));A[1,1:2]=1:0;A[N,n:N]=0:1;y=n^-2*sapply(x,f);y[1]=a;y[N]=b;plot(x,solve(A,y))}

असंगठित और समझाया गया:

u=function(f,a,b,N){
    n=N-1;                                              # Alias for N-1
    x=0:n/n;                                            # Generate the x-axis
    A=toeplitz(c(2,-1,rep(0,N-2)));                     # Generate the A-matrix
    A[1,1:2]=1:0;                                       # Replace first row--
    A[N,n:N]=0:1;                                       # Replace last row
    y=n^-2*sapply(x,f)                                  # Generate h^2*f(x)
    y[1]=a;y[N]=b;                                      # Replace first and last elements with uL(a) and uR(b)
    plot(x,solve(A,y))                                  # Solve the matrix system A*x=y for x and plot against x 
}

उदाहरण और परीक्षण के मामले:

नामित और अपुष्ट फ़ंक्शन का उपयोग करके कहा जा सकता है:

u(function(x)-2,0,0,10)
u(function(x)x*10,0,1,15)
u(function(x)sin(2*pi*x),1,1,20)
u(function(x)x^2,0,0,30)

ध्यान दें कि fतर्क एक आर-फ़ंक्शन है।

गोल्फ संस्करण चलाने के लिए बस का उपयोग करें (function(...){...})(args)

यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें


मुझे लगता है कि आप is.numeric(f)चेक को ड्रॉप कर सकते हैं यदि आप fफ़ंक्शन के रूप में घोषित करते हैं, तो इसे फ़ंक्शन कॉल में सीधे सॉल्वर में पास करने की आवश्यकता नहीं है।
कार्ल नेप

आह, मैं देखता हूं, मुझे नहीं पता था कि उन दोनों के बीच अंतर है। ठीक है, अगर यह छोटा है तो आप अपने सॉल्वर को fएक फ़ंक्शन के रूप में स्वीकार करने के लिए संशोधित कर सकते हैं, इसलिए आपको इस मामले की जांच करने की आवश्यकता नहीं है कि यह एक स्थिर (फ़ंक्शन) है।
कार्ल नेफ

1
@ बिलीवोब fको कभी भी संख्यात्मक होने की कोई आवश्यकता नहीं है । f = (function(x)-2)पहले उदाहरण के लिए काम करता है, इसलिए वहाँ कभी नहीं की जरूरत है rep
आंग्स

आप उपयोग कर सकते हैं x<-0:10/10;f<-function(x){-2};10^-2*sapply(x,f), तो f (x) सिर्फ vectorized किए जाने की quaranteed नहीं है या 10^-2*f(x)अगर fvectorized है ( laplace(Vectorize(function(x)2),0,0,10)
Angs

Eval का उपयोग न करें, fएक उचित कार्य के रूप में दें ।
एंग्स

2

हास्केल, 195 168 बाइट्स

import Numeric.LinearAlgebra
p f s e n|m<-[0..]!!n=((n><n)(([1,0]:([3..n]>>[[-1,2,-1]])++[[0,1]])>>=(++(0<$[3..n]))))<\>(col$s:map((/(m-1)^2).f.(/(m-1)))[1..m-2]++[e])

पठनीयता काफी हिट हुई। Ungolfed:

laplace f start end _N = linearSolveLS _M y
  where
  n = fromIntegral _N
  _M = (_N><_N) --construct n×n matrix from list
        ( ( [1,0]           --make a list of [1,0]
          : ([3.._N]>>[[-1,2,-1]]) --         (n-2)×[-1,2,-1]
          ++ [[0,1]])       --               [0,1]
        >>= (++(0<$[3.._N])) --append (n-2) zeroes and concat
        )                   --(m><n) discards the extra zeroes at the end
  h  = 1/(n-1) :: Double
  y  = asColumn . fromList $ start : map ((*h^2).f.(*h)) [1..n-2] ++ [end]

TODO: 83 71 बाइट्स में छपाई ।

मुझे देखने दो:

import Graphics.Rendering.Chart.Easy
import Graphics.Rendering.Chart.Backend.Cairo

डी 'ओह!


मैं हास्केल के बारे में ज्यादा नहीं जानता, लेकिन शायद मैट्रिक्स बीजगणित के बिना समाधान कम हो सकता है, मैंने एक दूसरा नमूना कार्यान्वयन जोड़ा।
कार्ल नेफ

@KarlNapf बहुत करीब नहीं आता है यह केवल अर्ध-गोल्फ है लेकिन इसमें बहुत सारे वर्बोज़ अंतर्निहित कार्यों का उपयोग करना है। मैट्रिक्स बीजगणित के साथ अधिकांश कोड मैट्रिक्स (64 बाइट्स) और आयात (29 बाइट्स) का निर्माण कर रहे हैं। अवशिष्ट और जैकोबी काफी जगह लेते हैं।
19

खैर, बहुत बुरा है, लेकिन यह एक कोशिश के काबिल था।
कार्ल नेफ

1

Axiom, 579 460 बाइट्स

l(w,y)==(r:=0;for i in 1..y|index?(i,w)repeat r:=i;r)
g(z:EQ EXPR INT,y:BasicOperator,a0:Float,a1:Float,a2:Float):Float==(r:=digits();digits(r+30);q:=seriesSolve(z,y,x=0,[a,b])::UTS(EXPR INT,x,0);w:=eval(q,0);s:=l(w,r+30);o:=solve([w.s=a0,eval(q,1).s=a1]::List(EQ POLY Float),[a,b]);v:=eval(eval(eval(q,a2).s,o.1.1),o.1.2);digits(r);v)
m(z:EXPR INT,a0:Float,a1:Float,n:INT):List Float==(n:=n-1;y:=operator 'y;r:=[g(D(y x,x,2)=-z,y,a0,a1,i/n)for i in 0..n];r)

यह ungolf और परीक्षण

Len(w,y)==(r:=0;for i in 1..y|index?(i,w)repeat r:=i;r)

-- g(z,a0,a1,a2)
-- Numeric solve z as f(y''(x),y'(x),y(x))=g(x) with ini conditions y(0)=a0   y(1)=a1 in x=a2
NSolve2order(z:EQ EXPR INT,y:BasicOperator,a0:Float,a1:Float,a2:Float):Float==
      r:=digits();digits(r+30)
      q:=seriesSolve(z,y,x=0,[a,b])::UTS(EXPR INT,x,0)
      w:=eval(q,0);s:=Len(w,r+30)
      o:=solve([w.s=a0,eval(q,1).s=a1]::List(EQ POLY Float),[a,b])
      v:=eval(eval(eval(q,a2).s,o.1.1),o.1.2);digits(r)
      v

InNpoints(z:EXPR INT,a0:Float,a1:Float,n:INT):List Float==(n:=n-1;y:=operator 'y;r:=[NSolve2order(D(y x,x,2)=-z,y,a0,a1,i/n)for i in 0..n];r)

प्रश्न के लिए फ़ंक्शन m (,,,) है। उपरोक्त कोड "file.input" फ़ाइल में डाला गया है और Axiom में लोड किया गया है। परिणाम अंकों () फ़ंक्शन से निर्भर करता है।

अगर किसी को लगता है कि यह गोल्फ नहीं है => वह या वह दिखा सकता है कि यह कैसे करना है ... धन्यवाद

पुनश्च

ऐसा लगता है कि 6 संख्याएं आगे हैं। e ^ (x ^ 2) के लिए यहां या उदाहरणों में ठीक नहीं है, लेकिन यहां मैं अंकों को बढ़ाता हूं, लेकिन संख्याएं नहीं बदलती हैं ... मेरे लिए इसका मतलब है कि उदाहरण में संख्याएं गलत हैं। अन्य सभी ने अपनी संख्या क्यों नहीं दिखाई?

पाप के लिए (2 *% pi * x) समस्याएं भी हैं

"यहाँ सटीक समाधान है u = (sin (2 *) * x)) / (4 * 2 ^ 2) +1" मैंने x = 1/19 के सटीक समाधान की प्रतिलिपि बनाई:

              (sin(2*π/19))/(4*π^2)+1

वुल्फरामअल्फा में https://www.wolframalpha.com/input/?i=(sin(2% CF% 80% 2F19))% 2F (4 % CF% 80% 5E2)% 2B1 यह परिणाम है

1.008224733636964333380661957738992274267070440829381577926...
1.0083001
  1234
1.00822473

परिणाम के रूप में प्रस्तावित 1.0083001 4 अंक में वास्तविक परिणाम 1.00822473 से भिन्न है ... (और 6 वें नहीं)

-- in interactive mode
(?) -> )read  file
(10) -> digits(9)
   (10)  10
                                                        Type: PositiveInteger
(11) -> m(-2,0,0,10)
   (11)
   [0.0, - 0.0987654321, - 0.172839506, - 0.222222222, - 0.24691358,
    - 0.24691358, - 0.222222222, - 0.172839506, - 0.098765432, 0.0]
                                                             Type: List Float
(12) -> m(10*x,0,1,15)
   (12)
   [0.0, 0.189868805, 0.376093294, 0.555029155, 0.72303207, 0.876457726,
    1.01166181, 1.125, 1.21282799, 1.27150146, 1.29737609, 1.28680758,
    1.2361516, 1.14176385, 1.0]
                                                             Type: List Float
(13) -> m(sin(2*%pi*x),1,1,20)
   (13)
   [1.0, 1.00822473, 1.01555819, 1.02120567, 1.0245552, 1.02524378, 1.02319681,
    1.0186361, 1.01205589, 1.00416923, 0.99583077, 0.987944112, 0.981363896,
    0.976803191, 0.97475622, 0.975444804, 0.978794326, 0.98444181, 0.991775266,
    1.0]
                                                         Type: List Float
(14) -> m(exp(x^2),0,0,30)
   (14)
   [0.0, 0.0202160702, 0.0392414284, 0.0570718181, 0.0737001105, 0.0891162547,
    0.103307204, 0.116256821, 0.127945761, 0.138351328, 0.147447305,
    0.155203757, 0.161586801, 0.166558343, 0.170075777, 0.172091643,
    0.172553238, 0.171402177, 0.168573899, 0.163997099, 0.157593103,
    0.149275146, 0.13894757, 0.126504908, 0.111830857, 0.0947971117,
    0.0752620441, 0.0530692118, 0.0280456602, - 0.293873588 E -38]
                                                             Type: List Float

संख्यात्मक समाधान सटीक समाधान से भिन्न होता है क्योंकि यहाँ FDM केवल दूसरा क्रम है, इसका मतलब है कि केवल क्रम 2 तक के बहुपद का ठीक-ठीक प्रतिनिधित्व किया जा सकता है। तो केवल f=-2उदाहरण के लिए एक मिलान विश्लेषणात्मक और संख्यात्मक समाधान है।
कार्ल नेफ

अगर मैं 80 या 70 में अंक बदलता हूं तो संख्यात्मक समाधान ठीक है -> जी (पाप (2 *% pi * x), 1,1,1 / 19) 1.0082247336 3696433338 0661957738 9922262670 7044082938 1577926908 950765832 और अन्य नंबर 1.0082247336 7044082938 1577926 ...
रोज़लूपी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.