我必须解决Euler Bernoulli微分梁方程:
w’’’’(x) = q(x)
和边界条件:
w(0) = w(l) = 0
和
w′′(0) = w′′(l) = 0
光束如下图所示:
持续的力q
是2N/mm
。
我必须使用拍摄方法和scipy.integrate.odeint()
func。
我甚至无法开始,因为我不明白如何将微分方程写为方程组
能够理解在python中解决具有边界条件的微分方程的人可以帮忙!
谢谢:)
答案 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)=0
和w
的初始边界条件。
向当前状态# 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 derivative
是w
所以我们将其添加到{{} 1}}等等。
3。)现在我们可以设置shooting method
。我们会将different initial boundary values
w'(0)
和w'''(0)
发送至odeint()
,然后检查returned w(x) profile
的最终结果,以确定w(L)
和w''(L)
的距离。 0
已known
(# 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 conditions
。 system 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)=0
和F = 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
的结果是正确的。
要将xSteps
增加u2_u4_maxNumbers
和u2Numbers
更大的数字得到更好的结果,您还可以将u4Numbers
和same 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系统。由于系统是线性的,拍摄功能也是线性的,你只需要找到系数并求解最终的线性系统。