欧拉梁,求解python中的微分方程

时间:2018-01-02 12:19:49

标签: python-3.x differential-equations

我必须解决Euler Bernoulli微分梁方程:

w’’’’(x) = q(x)

和边界条件:

w(0) = w(l) = 0 

w′′(0) = w′′(l) = 0

光束如下图所示:

beam

持续的力q2N/mm

我必须使用拍摄方法和scipy.integrate.odeint() func。

我甚至无法开始,因为我不明白如何将微分方程写为方程组

能够理解在python中解决具有边界条件的微分方程的人可以帮忙!

谢谢:)

2 个答案:

答案 0 :(得分:3)

拍摄方法

要使用fourth order ODE BVP scipy.integrate.odeint()解决shooting method,您需要:

1。)4th order ODE分隔为4 first order ODEs代替:

u = w
u1 = u' = w'           # 1
u2 = u1' = w''         # 2
u3 = u2' = w'''        # 3
u4 = u3' = w'''' = q   # 4

2。)创建function以执行derivation logic并将此功能连接到integrate.odeint(),如下所示:

function calc(u, x , q)
{
    return [u[1], u[2], u[3] , q]
}

w = integrate.odeint(calc, [w(0), guess, w''(0), guess], xList, args=(q,))

<强>解释

我们将odeint()x=0)的边界值条件发送给[w(0), w'(0) ,w''(0), w'''(0)],该calc调用函数w,该函数返回要添加到当前状态的导数w'(0)。请注意,我们在输入已知w'''(0)w(0)=0时猜测w''(0)=0w的初始边界条件。

向当前状态# the current w(x) value is the previous value plus the current change of w in dx. w(x) = w(x-dx) + dw/dx # others are calculated the same dw(x)/dx = dw(x-dx)/dx + d^2w(x)/dx^2 # etc. 添加衍生物的方式如下:

[u[1], u[2], u[3] , q]

这就是我们从[u[0], u[1], u[2] , u[3]]返回值calc function而不是u[1]的原因,因为first derivativew所以我们将其添加到{{} 1}}等等。

3。)现在我们可以设置shooting method。我们会将different initial boundary values w'(0)w'''(0)发送至odeint(),然后检查returned w(x) profile的最终结果,以确定w(L)w''(L)的距离。 0known# a function to return the derivatives of w def returnDerivatives(u, x, q): return [u[1], u[2], u[3], q] # a shooting funtion which takes in two variables and returns a w(x) profile for x=[0,L] def shoot(u2, u4): # the number of x points to calculate integration -> determines the size of dx # bigger number means more x's -> better precision -> longer execution time xSteps = 1001 # length of the beam L= 1.0 # 1m xSpace = np.linspace(0, L, xSteps) q = 0.02 # constant [N/m] # integrate and return the profile of w(x) and it's derivatives, from x=0 to x=L return odeint(returnDerivatives, [ 0, u2, 0, u4] , xSpace, args=(q,)) # the tolerance for our results. tolerance = 0.01 # how many numbers to consider for u2 and u4 (the guess boundary conditions) u2_u4_maxNumbers = 1327 # bigger number, better precision, slower program # you can also divide into separate variables like u2_maxNum and u4_maxNum # these are already tested numbers (the best results are somewhere in here) u2Numbers = np.linspace(-0.1, 0.1, u2_u4_maxNumbers) # the same as above u4Numbers = np.linspace(-0.5, 0.5, u2_u4_maxNumbers) # result list for extracted values of each w(x) profile => [u2Best, u4Best, w(L), w''(L)] # which will help us determine if the w(x) profile is inside tolerance resultList = [] # result list for each U (or w(x) profile) => [w(x), w'(x), w''(x), w'''(x)] resultW = [] # start generating numbers for u2 and u4 and send them to odeint() for u2 in u2Numbers: for u4 in u4Numbers: U = [] U = shoot(u2,u4) # get only the last row of the profile to determine if it passes tolerance check result = U[len(U)-1] # only check w(L) == 0 and w''(L) == 0, as those are the known boundary cond. if (abs(result[0]) < tolerance) and (abs(result[2]) < tolerance): # if the result passed the tolerance check, extract some values from the # last row of the w(x) profile which we will need later for comaprisons resultList.append([u2, u4, result[0], result[2]]) # add the w(x) profile to the list of profiles that passed the tolerance # Note: the order of resultList is the same as the order of resultW resultW.append(U) # go through the resultList (list of extracted values from last row of each w(x) profile) for i in range(len(resultList)): x = resultList[i] # both boundary conditions are 0 for both w(L) and w''(L) so we will simply add # the two absolute values to determine how much the sum differs from 0 y = abs(x[2]) + abs(x[3]) # if we've just started set the least difference to the current if i == 0: minNum = y # remember the smallest difference to 0 index = 0 # remember index of best profile elif y < minNum: # current sum of absolute values is smaller minNum = y index = i # print out the integral for w(x) over the beam sum = 0 for i in resultW[index]: sum = sum + i[0] print("The integral of w(x) over the beam is:") print(sum/1001) # sum/xSteps 边界条件)。

拍摄方法的程序:

The integral of w(x) over the beam is:
0.000135085272117

输出:

w(x)

打印出我们找到的print(resultW[index]) 的最佳资料:

 #       w(x)             w'(x)           w''(x)           w'''(x)
[[  0.00000000e+00   7.54147813e-04   0.00000000e+00  -9.80392157e-03]
 [  7.54144825e-07   7.54142917e-04  -9.79392157e-06  -9.78392157e-03]
 [  1.50828005e-06   7.54128237e-04  -1.95678431e-05  -9.76392157e-03]
 ..., 
 [ -4.48774290e-05  -8.14851572e-04   1.75726275e-04   1.01560784e-02]
 [ -4.56921910e-05  -8.14670764e-04   1.85892353e-04   1.01760784e-02]
 [ -4.65067671e-05  -8.14479780e-04   1.96078431e-04   1.01960784e-02]]

输出如下内容:

ODE

<小时/> 要仔细检查上面的结果,我们还会使用numerical method解决numerical method

数值方法

要使用solve the differential equations来解决问题,我们首先需要four constants。在boundary conditions的帮助下,我们需要找到boundary conditionssystem of equations将用于形成constants,以帮助您找到必要的w’’’’(x) = q(x);

例如:

d^4(w(x))/dx^4 = q(x)

意味着我们有:

q(x)

由于d^3(w(x))/dx^3 = q(x)*x + C 在积分后是常数,我们有:

d^2(w(x))/dx^2 = q(x)*0.5*x^2 + C*x + D

再次整合后:

dw(x)/dx = q(x)/6*x^3 + C*0.5*x^2 + D*x + E

经过另一次整合:

w(x) = q(x)/24*x^4 + C/6*x^3 + D*0.5*x^2 + E*x + F

最后,最后的整合产生了:

boundary conditions

然后我们来看w''(x)(现在我们有w(x)system of equations的上面的表达式),我们用它来constants来解决w''(0) => 0 = q(x)*0.5*0^2 + C*0 + D w''(L) => 0 = q(x)*0.5*L^2 + C*L + D 1}}。

constants

这为我们提供了D = 0 # from the first equation C = - 0.01 * L # from the second (after inserting D=0)

w(0)=0

重复w(L)=0F = 0 # from first E = 0.01/12.0 * L^3 # from second 后,我们获得:

solved the equation

现在,在我们integration constants找到所有numerical method之后,我们可以为FOR制作程序。

数值方法的程序

我们将制作一个dx循环,逐次浏览每个w(x)的整个波束,并总结(整合)L = 1.0 # in meters step = 1001.0 # how many steps to take (dx) q = 0.02 # constant [N/m] integralOfW = 0.0; # instead of w(0) enter the boundary condition value for w(0) result = [] for i in range(int(L*step)): x= i/step w = (q/24.0*pow(x,4) - 0.02/12.0*pow(x,3) + 0.01/12*pow(L,3)*x)/step # current w fragment # add up fragments of w for integral calculation integralOfW += w # add current value of w(x) to result list for plotting result.append(w*step); print("The integral of w(x) over the beam is:") print(integralOfW)

The integral of w(x) over the beam is:
0.00016666652805511192

输出:

w(x)

<小时/> 现在比较两种方法

射击方法与数值方法的结果比较

Shooting method -> 0.000135085272117 Numerical method -> 0.00016666652805511192 在光束上的积分:

shooting method

这是一个非常好的匹配,现在让我们看看图:

Shooting method vs Numerical method - ODE

从图中可以看出,我们有一个很好的匹配,shooting method的结果是正确的。

要将xSteps增加u2_u4_maxNumbersu2Numbers更大的数字得到更好的结果,您还可以将u4Numberssame set size but a smaller interval缩小到xSteps(围绕以前程序运行的最佳结果)。请注意,设置u2_u4_maxNumbers textA = self.HelperSelenium.getTextFromElement(self.Starter.WELCOME_VIEW()) 太高会导致程序运行很长时间。

答案 1 :(得分:2)

您需要将ODE转换为一阶系统,将u0=w设置为一个,并且通常使用的系统是

u0'=u1,
u1'=u2,
u2'=u3,
u3'=q(x)

这可以实现为

def ODEfunc(u,x): return [ u[1], u[2], u[3], q(x) ]

然后创建一个用实验初始条件拍摄的函数,并返回第二个边界条件的分量

def shoot(u01, u03): return odeint(ODEfunc, [0, u01, 0, u03], [0, l])[-1,[0,2]]

现在你有两个变量和两个组件的功能,你需要用常用方法解决这个2x2系统。由于系统是线性的,拍摄功能也是线性的,你只需要找到系数并求解最终的线性系统。