如何绘制三维图像:Plot3D NDSolve

时间:2011-11-18 08:11:57

标签: wolfram-mathematica

m = 10; c = 2; k = 5; F = 12;

NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], 
         x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}] 
  

{f,0,5}(0 =< f< = 5)

如何绘制三维图像:

  

x = u(t,f)

............

如果f = 0.1,0.2,... 5, 我们可以解决这个等式:

NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], 
         x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}] 

x是t和f

的函数

...............

m = 10; c = 2; k = 5; F = 12;

f = 0.1

s = NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], 
             x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}] 
Plot[Evaluate[x[t] /. s], {t, 0, 30}, PlotRange -> All]

f = 0.1 enter image description here

f = 0.2 enter image description here

f = 0.3 enter image description here

f = 5 enter image description here

如何绘制三维图像: x = u(t,f)

3 个答案:

答案 0 :(得分:6)

这是一个解决方案。

m = 10; c = 2; k = 5; F = 12;
NumberOfDiscrit$f = 20;(* Number of points you want to divide 0<=f<=5*)
NumberOfDiscrit$t = 100;(* Number of points you want to divide 0<=t<=30 *)
fValues = Range[0., 5., 5./(NumberOfDiscrit$f - 1)];
tValues = Range[0., 30., 30./(NumberOfDiscrit$t - 1)];
res = Map[(x /. 
  First@First@
    NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*#*t])*x[t] == 
       F*Sin[2*Pi*#*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30}]) &,
fValues];
AllDat = Map[(#@tValues) &, res];
InterpolationDat = 
Flatten[Table[
Transpose@{tValues, 
  Table[fValues[[j]], {i, 1, NumberOfDiscrit$t}], 
  AllDat[[j]]}, {j, 1, NumberOfDiscrit$f}], 1];
Final3DFunction = Interpolation[InterpolationDat];
Plot3D[Final3DFunction[t, f], {t, 0, 30}, {f, 0, 5}, PlotRange -> All,
PlotPoints -> 60, MaxRecursion -> 3, Mesh -> None]

enter image description here

您可以使用Manipulate动态更改某些参数。顺便说一下,如果在f中将u(t,f)作为连续变量,则上述3D图片可能会产生误导。你应该注意到,数值解似乎对t>>30的渐近值有所了解。见下图。

enter image description here enter image description here

希望这可以帮助你。

答案 1 :(得分:6)

你也可以这样做

Clear[f]
m = 10; c = 2; k = 5; F = 12;

s = NDSolve[{m*Derivative[2, 0][x][t, f] + 
     c*Derivative[1, 0][x][t, f] + (k*Sin[2*Pi*f*t])*x[t, f] == F*Sin[2*Pi*f*t],
   x[0, f] == 0,
   Derivative[1, 0][x][0, f] == 0}, x, {t, 0, 30}, {f, 0, .2}]

Plot3D[Evaluate[x[t, f] /. s[[1]]], {t, 0, 30}, {f, 0, .2}, PlotRange -> All]

3d plot

答案 2 :(得分:3)

这应该这样做。

m = 10; c = 2; k = 5; F = 12;


fun[f_?NumericQ] :=
 Module[
   {x, t}, 
   First[x /. 
     NDSolve[
      {m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
       x[0] == 0, x'[0] == 0}, 
      x, {t, 0, 30}
     ]
   ]
 ]

ContourPlot[fun[f][t], {f, 0, 5}, {t, 0, 30}]

重点:

  • 模式_?NumericQ阻止{symbol}参数的fun被评估(考虑fun[a]),并导致NDSolve::nlnum错误。

  • 由于NDSolve似乎没有本地化其功能变量(t),我们需要使用Module手动执行此操作以防止t之间发生冲突NDSolve中使用的ContourPlotContourPlot中使用的{}。 (你可以在Clear[funMemo] (* very important!! *) funMemo[f_?NumericQ] := funMemo[f] = Module[{x, t}, First[x /. NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30}]]] ContourPlot[funMemo[f][t], {f, 0, 5}, {t, 0, 30}] (* much faster than with fun *) 中使用不同名称的变量,但我认为指出这个警告很重要。)


如果在绘图方面有显着的加速,你可以使用memoization,正如巫师先生所指出的那样。

SetAttributes[memo, HoldAll]
SetAttributes[memoStore, HoldFirst]
SetAttributes[memoVals, HoldFirst]

memoVals[_] = {};

memoStore[f_, x_] := 
 With[{vals = memoVals[f]}, 
  If[Length[vals] > 100, f /: memoStore[f, First[vals]] =.;
   memoVals[f] ^= Append[Rest[memoVals[f]], x], 
   memoVals[f] ^= Append[memoVals[f], x]];
  f /: memoStore[f, x] = f[x]]

memo[f_Symbol][x_?NumericQ] := memoStore[f, x]

如果你喜欢冒险,并且愿意更深入地探索Mathematica,你可以通过限制允许使用缓存定义的内存量as I described here来进一步改善这一点。

让我们定义一个辅助函数来启用memoization:

fun

然后使用原始的,未记忆的ContourPlot[memo[fun][f][t], {f, 0, 5}, {t, 0, 30}] 函数,绘制为

{{1}}