【求助】NDSolve解一阶含有11个函数的偏微分方程组画出函数图像
mathematica吧
全部回复
仅看楼主
level 6
因为课题需要最近要解一个一阶含有11个函数的偏微分方程组,向学校解过这个方程组师兄和老师咨询了一下,他们是用的matlab,python,fotron等语言利用有限元或者有限差分法解的。了解到mathematica新增了一个NDSolve的函数功能,就想着尝试一下,因为这个方程组虽然函数多但是只是个一阶的,而且看到官方的帮助文档中有解耦合偏微分方程组的例子。Mathematica的解给出的是插值函数的形式,但是画图却是一片空白(因为函数中带有复数,所以最后画图时用了Abs函数;这个解是个光波的振幅项,最后需要取模平方)。
所以想请教下大家是NDSolve这个函数解不出这样的方程组还是说我的程序方面有问题,导致最后画出的图像是空白的。
以下是代码:
\[Theta] = 0; Subscript[N, A] = 6.022*10^23;
Subscript[r, 0] = 2.818/10^15;
\[Lambda] = 1.2398/20; f = 4.72;
Subscript[N, A] = 6.022*10^23;
Subscript[r, 0] = 2.818/10^13;
\[Lambda] = 1.2398/(19.5*10^7);
Subscript[f, 1] = 11.353;
Subscript[\[Rho], 1] = 2.33;
Subscript[A, 1] = (28.0855*1.66053886*10^3*Subscript[N, A])/10^27;
Subscript[\[Delta], 1] = (Subscript[N, A]/(2*Pi))*
Subscript[r, 0]*\[Lambda]^2*
Subscript[\[Rho], 1]*(Subscript[f, 1]/Subscript[A, 1]);
Subscript[f, 2] = 12.3246;
Subscript[\[Rho], 2] = 2.7;
Subscript[A, 2] = (26.981539*1.66053886*10^3*Subscript[N, A])/10^27;
Subscript[\[Delta], 2] = (Subscript[N, A]/(2*Pi))*
Subscript[r, 0]*\[Lambda]^2*
Subscript[\[Rho], 1]*(Subscript[f, 2]/Subscript[A, 2]);
Subscript[\[Mu], 1] = 2.9941*10^3; Subscript[\[Mu], 2] = 2.4456*10^3;
Subscript[bt, 1] = (\[Lambda]*Subscript[\[Mu], 1])/(4*Pi);
Subscript[bt, 2] = (\[Lambda]*Subscript[\[Mu], 2])/(4*Pi);
\[Chi]1 = -2*Subscript[\[Delta], 1] + 2*I*Subscript[bt, 1];
\[Chi]2 = -2*Subscript[\[Delta], 2] + 2*I*Subscript[bt, 2];
\[CapitalDelta]\[Chi] = \[Chi]1 - \[Chi]2;
Table[d1[f] = f*x^2 + 1, {f, 0, 5}];
Table[\[Beta][
b] = -2*((b*x)/f)*Sin[\[Theta]] - ((b*x)/(f*1000))^2, {b, -5, 5}];
Table[\[Chi][
a] = (\[CapitalDelta]\[Chi]/(2*I*a*Pi))*(1 - (-1)^
Abs[a]), {a, -10, -1}];
Table[\[Chi][
a] = (\[CapitalDelta]\[Chi]/(2*I*a*Pi))*(1 - (-1)^Abs[a]), {a, 1,
10}]; Table[\[Chi][a] = (\[Chi]1 + \[Chi]2)/2, {a, 0, 0}];
eqns = Join[
Table[(Sin[\[Theta]] + (h/(f*10^3))*x)*
D[Subscript[Y, h][x, z], x] +
Cos[\[Theta]]*D[Subscript[Y, h][x, z], z] ==
((I*Pi)/(\[Lambda]/10^4))*(\[Beta][h]*
Subscript[Y, h][x, z] +
Sum[\[Chi][h - l]*Subscript[Y, l][x, z], {l, -5,
5}]), {h, -5, 5}],
Table[Subscript[Y, h][x, 0] == 0, {h, -5, -1}],
Table[Subscript[Y, h][x, 0] == 0, {h, 1, 5}],
Table[Subscript[Y, h][x, 0] == 1, {h, 0, 0}]];
s = NDSolve[eqns,
Table[Subscript[Y, h][x, z], {h, -5, 5}], {x, 0, 30}, {z, 0, 30}]
Plot3D[Evaluate[Abs[Y[-1][x, z] /. s]], {x, 0, 30}, {z, 0, 30},
PlotLegends -> Automatic]
2020年12月31日 01点12分 1
level 6
这是解出的插值函数形式的解,我尝试过查看插值函数解得具体数值,但是试了几个函数之后都没能尝试出,看了官方的帮助文档发现一些函数的差值函数解能查看出具体的数值\("▔□▔)/
2020年12月31日 01点12分 2
level 9
这里面有个替换的问题:
它并没有替换成你想要的结果,而是变成了Y_-1[x,z],而你想要的结果是:
解决办法请参考吧主贴《为什么我的代码加了下标(Subscript)就出问题了?》:https://tieba.baidu.com/p/6149871454?pid=125906218284&cid=0#125906218284
我手动改了一下,输出了其中一个结果,发现你的数据可能有点问题,也忒小了
建议把整个问题发出来看看
2021年01月01日 06点01分 3
level 9
我发的东西呢?被删了????
2021年01月01日 06点01分 4
现在已经恢复了……你申诉了?还是百度自动吐出来的?
2021年01月02日 03点01分
@xzcyr 我申述了[喷]
2021年01月02日 03点01分
level 9
居然被删了,我真的吐了,我再发一遍吧
这一句替换有问题:
正确的
结果应该是这样的:
这里面的错误是下标的问题,可以参考吧主发的《为什么我的代码加了下标(Subscript)就出问题了?》,我就不放链接了,免得又被删除
我把你计算的结果调出来看了看,发现数据太小而且有虚数:
可能你计算过程有问题,建议把完整的题目放出来看看
2021年01月01日 06点01分 5
这里确切地说不是下标问题,单纯是LZ把 Y[-1] 和 Subscript[Y, -1] 搞混了,不知道是疏忽还是他真以为这两个东西是一回事……还有他的代码里的问题不止这个,参楼下。
2021年01月02日 03点01分
感谢您的回复。这个问题的话是一篇x射线动力学衍射的文献中最后化简出的方程组,方程组和边界条件本身应该是没问题的,可能我有的参数本身有问题,这点我再和老师确认一下。下标的问题的话我以为这两个东西是一码事[惊哭] 我先把参数和下标的问题解决一下后再试试看
2021年01月02日 06点01分
@xzcyr Y[-1][x,z]和Subscript[Y,-1][x,z]因为我看案例里有用Y[-1][x,z]这种表示方程组的,而且最后我输出的形式中看起来这两者在方程组中长得是一样的,都是下标的形式。所以我认为他们是一样的[惊哭][惊哭]但是实际上他们在方程组中是表示不一样的函数嘛?
2021年01月02日 07点01分
@薛定谔那只该死的喵嗷 ……哪里一样了?Y[-1]你不专门去改它的显示形式它是不会变成下标的。更多内容参考《为什么我的代码加了下标(Subscript)就出问题了?》那帖。
2021年01月02日 07点01分
吧务
level 15
“了解到mathematica新增了一个NDSolve的函数功能”,NDSolve引入时间是版本2.0(1991年),并且至少从版本3.0(1996年)起就能解偏微分方程了。当然,性能可能不及现在。
“因为这个方程组虽然函数多但是只是个一阶的”,纯一阶偏微分方程的数值解反倒是最麻烦的,因为它们的经典解理论上只用在一个方向上给出限制条件,但是数值求解的时候,每个有导数的维度都必须要给出限制条件,而要使额外给定的那个条件与已有的条件一致有时很麻烦——其实不给也不是完全不可以,但是那样就只有特征线围着的区域,或者说初始条件能够“管到”的那一块区域里的解可信了。这里不再展开说,感兴趣的去找本介绍了一阶波动方程(输运方程)的书看看。总之,LZ在求解时只给NDSolve输入了 z 方向上的边界条件(顺便 NDSolve 此时也跳了 bcart 警告),这是个非常严重的问题,不要因为 NDSolve 此时依旧输出了一个解就**大意!更多内容可以参看 stackexchange 帖子《What boundary is added when boundary condition is not sufficient?》(编号73961),链接就不贴了,怕被吞。
另,你似乎搞错了PlotLegends的意思,请仔细看帮助。
最后,此类一阶方程有两个可以视作“时间”的方向,有时候需要手动指定"TemporalVariable",你这个似乎就属此例,总之把最后一部分代码改为
bc = Table[Subscript[Y, h][30, z] == If[h == 0, 1, 0], {h, -5, 5}];
s = NDSolve[{eqns, bc}, Table[Subscript[Y, h][x, z], {h, -5, 5}], {x, 0, 30}, {z, 0, 30},
Method -> {"MethodOfLines",
"SpatialDiscretization" -> {"TensorProductGrid", "MaxPoints" -> 100,
"MinPoints" -> 100, "DifferenceOrder" -> 4}, "TemporalVariable" -> z}];
Plot3D[Evaluate[Abs[Subscript[Y, 0][x, z] /. s]], {x, 0, 30}, {z, 0, 30},
AxesLabel -> Automatic, PlotRange -> All]
就能出结果了:
不过可不可靠就只有你知道了。3楼和5楼也说了,微分方程求解一定要保证方程本身是正确的——这听起来或许像句废话,但是它对微分方程求解就是这么重要,因为微分方程的求解工作太过繁重,“方程本身有错”带来的“伤害”太大了。
2021年01月02日 03点01分 6
感谢吧主的回复。这个方程本身应该是文献中的推导结果,叫做TTD方程。边界条件只有z=0时的数值,因为只能确定出入射波场的设定值,这个边界条件我是按照文献给的,因为目前这个方程组的引用量挺高的,各个文章中解这个方程组的边界条件也都一样,所以没想过边界条件的问题
2021年01月02日 06点01分
可能是有些地方文章中没给出来所以被疏忽了?这点我再和师兄们确认一下,看看哪里出了问题
2021年01月02日 06点01分
@薛定谔那只该死的喵嗷 如果方程是从文献里找的,强烈建议先试试文献里的结果能否重现。
2021年01月02日 09点01分
@xzcyr 我这个就是先抄的原文献的形式验证自己解的对不对[紧张]结果现在验证的显而易见不对[喷][喷]
2021年01月02日 10点01分
level 6
这是我自己画的图:
这是文献的图,可以看出来形状上和范围上还是有不小的差距的。
2021年01月02日 15点01分 7
从图形来看文献很可能在x=30微米处设了值为0的第一类边界,而你的没有。
2021年01月02日 15点01分
当然也可能是波动还没有传导到x=30。但4条边界有3条对不上明显不正常。
2021年01月02日 15点01分
@xzcyr 我设了一下,发现好像最后画出的图没啥区别[喷]
2021年01月02日 15点01分
@xzcyr 是的,很不正常[喷] 但是边界条件应该是没有了,我有看了好多篇这个方程的文献,边界条件都没有变化[喷]我再好好排查下是不是我的方程组参数有什么问题[喷]
2021年01月02日 15点01分
level 6
具体的运行如下图
直接输入数值时没有返回原函数
加上等于号就行了
2021年01月08日 05点01分 8
吧务
level 15
LZ在SE的帖子是《When I define a Piecewise function containing a solution to a partial differential equation, the function cannot be evaluated numerically》(编号237842),该说的都在那边说了,也都是些基础问题,这里就不重复了。
2021年02月06日 04点02分 9
在此基础上写了篇教程:https://tieba.baidu.com/p/7219906432
2021年02月06日 07点02分
1