Это должно сделать это.
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 не позволяет fun
быть оцененным для аргументов символов (например, fun[a]
) и вызывать NDSolve::nlnum
ошибок.
Поскольку NDSolve
, по-видимому, не локализует свою переменную функции (t
), нам нужно было сделать это вручную, используя Module
, чтобы предотвратить конфликт между t
, используемым в NDSolve
, и один используется в ContourPlot
. (Вы можете использовать переменную с другим именем в ContourPlot
, но я думаю, что важно указать на это предостережение.)
Для значительного ускорения печати вы можете использовать памятка , как указал мистер Волшебник.
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 *)
Если вы чувствуете себя предприимчивым и хотите более глубоко изучить Mathematica, вы можете улучшить это, ограничив объем памяти, который разрешено использовать в кэшированных определениях, , как я описал здесь .
Давайте определим вспомогательную функцию для включения запоминания:
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]
Затем с использованием оригинальной незапамятной функции fun
, вычерчивайте как
ContourPlot[memo[fun][f][t], {f, 0, 5}, {t, 0, 30}]