当使用带有选项 algebraicOutputFormat 的 pstODEsolve 时,我想使用一个函数 \z,该函数本身由另一个 ode 解的“最终值”定义,参数 #1 是需要积分的时间
\documentclass[border=0pt,10pt,dvipsnames]{standalone}
\usepackage{amsmath}
\usepackage{pstricks}
\usepackage{dashrule}
\usepackage{pst-plot}%, pst-math}
\usepackage{pst-func}
\usepackage{pst-ode}
\usepackage{pst-3dplot}
\usepackage{pst-solides3d}
\usepackage[off]{auto-pst-pdf}
\usepackage[nomessages]{fp}
\psset{algebraic,unit=2}
\usepackage[active,tightpage]{preview}
\PreviewBorder=12pt
\PreviewEnvironment{pspicture}
\makeatletter
\define@key[psset]{}{valuerange}[1-]{\expandafter\pst@getrange#1\@nil}
\def\pst@getrange#1-#2\@nil{%
\ifx\relax#1\relax \def\pst@startvalue{1 }\else\def\pst@startvalue{#1 }\fi%
\ifx\relax#2\relax \def\pst@endvalue{1e32 }\else\def\pst@endvalue{#2 }\fi%
}
\psset{valuerange=1-}
\def\listplotIIID{\def\pst@par{}\pst@object{listplotIIID}}
\def\listplotIIID@i#1{%
\@nameuse{beginplot@\psplotstyle}%
\addto@pscode{%
/viewpointXYZ {\pst@solides@viewpoint} def
/Decran \pst@solides@Decran\space def % distance de l'ecran
viewpointXYZ /ZpointVue ED /YpointVue ED /XpointVue ED
/THETA {YpointVue XpointVue atan} bind def
/PHI {ZpointVue XpointVue dup mul YpointVue dup mul add sqrt atan} bind def
/Dobs {XpointVue dup mul YpointVue dup mul add ZpointVue dup mul add sqrt} bind def
XpointVue YpointVue ZpointVue /viewpoint defpoint3d
/XYZ [#1] def
/@tabXYZ [
0 3 XYZ length 3 sub {
/i exch def
XYZ i get
XYZ i 1 add get
XYZ i 2 add get
i 3 div dup /ii ED
\pst@startvalue ge {
ii \pst@endvalue le {
3dto2d
\pst@number\psunit mul exch
\pst@number\psunit mul exch
} { pop pop pop } ifelse
}{ pop pop pop } ifelse
} for
] bind def
[ @tabXYZ aload pop
}%
\@nameuse{endplot@\psplotstyle}}%
\makeatother
\def\r(#1){sin(#1)}
\def\rs(#1){cos(#1)}
\def\rss(#1){-sin(#1)}
\def\rssrs(#1){-sin(#1)*cos(#1)}
\def\zsq(#1){sin(#1)*sin(#1)*(1+cos(#1)+sin(2*#1)*sin(2*#1)/16)}
\def\zsszs(#1){(1/2)*sin(2*#1)*(1+cos(#1)+sin(2*#1)*sin(2*#1)/16)+(1/2)*sin(#1)*sin(#1)*(-sin(#1)+sin(4*#1)/8)}
%%%%%
%%%%% How to define a function as the "last" value of a numerical solution
%%%%% to an ODE where the variable #1 is the time to be integrated over
%%%%% starting from time = 0 in this example
%%%%%
%%%%% the following is of course not defined!
%%%%%
\def\z(#1){ "last value of" \pstODEsolve[algebraic,algebraicT]{test}{1}{0}{#1}{50}{0 1}{ 1 |
-sin(x[0])*sqrt(1+cos(x[0])+sin(2*x[0])*sin(2*x[0])/16)} }
\begin{document}
\begin{pspicture}(-1.2,-1)(3.1,1.1)
\psset[pst-solides3d]{viewpoint=20 5 20,Decran=20,lightsrc=viewpoint}
\pstODEsolve[algebraic,algebraicOutputFormat]{test}{\r(x[2])*sin(x[0]) | \z(x[2])
| \r(x[2])*cos(x[0])}{0}{22}{200}{1.57 1 0.3 0}{ x[1] | -2*\rs(x[2])*x[1]*x[3]/(\r(x[2]))| x[3] | -(\rssrs(x[2])+\zsszs(x[2]))*x[3]*x[3]/(\rs(x[2])*\rs(x[2])+\zsq(x[2]))
+\rs(x[2])*\r(x[2])*x[1]*x[1]/(\rs(x[2])*\rs(x[2])+\zsq(x[2]))}
\listplotIIID[linecolor=black,linewidth=1pt]{test}
\axesIIID(1,4,1)(2,4.5,2)
\end{pspicture}
\end{document}
答案1
\pstODEsolve
不可嵌套。
幸运的是,在目前的情况下,我们可以解决这个问题,因为请求的函数z(x)
将作为后处理步骤应用于主 ODE 解的第二列。
这可以通过两步程序实现。
1) 主要微分方程的解没有将 z(x) 应用于输出向量的第二个元素:
\pstODEsolve[algebraic,algebraicOutputFormat,saveData]{intermediateResult}{%
\r(x[2])*sin(x[0]) |
x[2] | % we process this column later
\r(x[2])*cos(x[0])
}{0}{22}{200}{1.57 1 0.3 0}{
x[1] | -2*\rs(x[2])*x[1]*x[3]/(\r(x[2]))| x[3] |
-(\rssrs(x[2])+\zsszs(x[2]))*x[3]*x[3]/(\rs(x[2])*\rs(x[2])+\zsq(x[2]))
+\rs(x[2])*\r(x[2])*x[1]*x[1]/(\rs(x[2])*\rs(x[2])+\zsq(x[2]))
}
并将解决方案表写入文件intermediateResult.dat
2)逐行读取中间文件中的表格,应用另一个 ODE
% two output points--v
\pstODEsolve[algebraic,algebraicT]{processedValue}{1}{0}{#1}{2}{0 1}{
1 | -sin(x[0])*sqrt(1+cos(x[0])+sin(2*x[0])*sin(2*x[0])/16)
}%
在输入行的第二个元素上,从存储的结果中取出最后一个值processedValue
并重新组装表格。
由于 PS --> PDF 转换步骤涉及写入和读取文本文件,因此ps2pdf
必须给出选项-dNOSAFER
。
跑步:
latex <...> dvips <...> ps2pdf -dNOSAFER <...>.ps
对以下输入文件执行两次:
\documentclass[border=10pt]{standalone}
\usepackage{pstricks}
\usepackage{pst-plot}%, pst-math}
\usepackage{pst-ode}
\usepackage{pst-solides3d}
\psset{algebraic,unit=2}
\makeatletter
\define@key[psset]{}{valuerange}[1-]{\expandafter\pst@getrange#1\@nil}
\def\pst@getrange#1-#2\@nil{%
\ifx\relax#1\relax \def\pst@startvalue{1 }\else\def\pst@startvalue{#1 }\fi%
\ifx\relax#2\relax \def\pst@endvalue{1e32 }\else\def\pst@endvalue{#2 }\fi%
}
\psset{valuerange=1-}
\def\listplotIIID{\def\pst@par{}\pst@object{listplotIIID}}
\def\listplotIIID@i#1{%
\@nameuse{beginplot@\psplotstyle}%
\addto@pscode{%
/viewpointXYZ {\pst@solides@viewpoint} def
/Decran \pst@solides@Decran\space def % distance de l'ecran
viewpointXYZ /ZpointVue ED /YpointVue ED /XpointVue ED
/THETA {YpointVue XpointVue atan} bind def
/PHI {ZpointVue XpointVue dup mul YpointVue dup mul add sqrt atan} bind def
/Dobs {XpointVue dup mul YpointVue dup mul add ZpointVue dup mul add sqrt} bind def
XpointVue YpointVue ZpointVue /viewpoint defpoint3d
/XYZ [#1] def
/@tabXYZ [
0 3 XYZ length 3 sub {
/i exch def
XYZ i get
XYZ i 1 add get
XYZ i 2 add get
i 3 div dup /ii ED
\pst@startvalue ge {
ii \pst@endvalue le {
3dto2d
\pst@number\psunit mul exch
\pst@number\psunit mul exch
} { pop pop pop } ifelse
}{ pop pop pop } ifelse
} for
] bind def
[ @tabXYZ aload pop
}%
\@nameuse{endplot@\psplotstyle}}%
\makeatother
\def\r(#1){sin(#1)}
\def\rs(#1){cos(#1)}
\def\rss(#1){-sin(#1)}
\def\rssrs(#1){-sin(#1)*cos(#1)}
\def\zsq(#1){sin(#1)*sin(#1)*(1+cos(#1)+sin(2*#1)*sin(2*#1)/16)}
\def\zsszs(#1){(1/2)*sin(2*#1)*(1+cos(#1)+sin(2*#1)*sin(2*#1)/16)+(1/2)*sin(#1)*sin(#1)*(-sin(#1)+sin(4*#1)/8)}
%for parsing lines of intermediateResult.dat
\def\getFirstOfThree#1 #2 #3;{#1}
\def\getSecondOfThree#1 #2 #3;{#2}
\def\getThirdOfThree#1 #2 #3;{#3}
\IfFileExists{intermediateResult.dat}{%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% second pass:
%
% post-process table --> z(second column)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% initialise Postscript variable to take the processed table
\pstVerb{%
true setglobal
globaldict /processedTable {} put
false setglobal
}%
\endlinechar=-1% suppress trailing space at input line end
\newread\xIIfile%
\openin\xIIfile=intermediateResult.dat%
%line-wise read table from `intermediateResult.dat', treat second column
\loop\read\xIIfile to \inputline%
\ifeof\xIIfile\else%
\pstODEsolve[algebraic,algebraicT]{processedVal}{1}{0}{\expandafter\getSecondOfThree\inputline;}{2}{0 1}{ 1 |
-sin(x[0])*sqrt(1+cos(x[0])+sin(2*x[0])*sin(2*x[0])/16)}%
%process input line and append result to postscript variable `processedTable' (executable list)
\pstVerb{
true setglobal
globaldict /processedTable [
processedTable
\expandafter\getFirstOfThree\inputline;\space
processedVal exch pop % insert second value and throw the first at t=0 away
\expandafter\getThirdOfThree\inputline;] cvx put
false setglobal
}%
\repeat%
}{%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% first pass
%
% solve main ODE without special treatment for second column of the solution table
% write solution to file `intermediateResult.dat'
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pstODEsolve[algebraic,algebraicOutputFormat,saveData]{intermediateResult}{%
\r(x[2])*sin(x[0]) |
x[2] | % we process this column later
\r(x[2])*cos(x[0])
}{0}{22}{200}{1.57 1 0.3 0}{
x[1] | -2*\rs(x[2])*x[1]*x[3]/(\r(x[2]))| x[3] |
-(\rssrs(x[2])+\zsszs(x[2]))*x[3]*x[3]/(\rs(x[2])*\rs(x[2])+\zsq(x[2]))
+\rs(x[2])*\r(x[2])*x[1]*x[1]/(\rs(x[2])*\rs(x[2])+\zsq(x[2]))}%
}%
\begin{document}
\IfFileExists{intermediateResult.dat}{%
%plot the resulting graph
\begin{pspicture}(-1.2,-1)(3.1,1.1)
\psset[pst-solides3d]{viewpoint=20 5 20,Decran=20,lightsrc=viewpoint}
\listplotIIID[linecolor=black,linewidth=1pt]{processedTable}
\axesIIID(1,4,1)(2,4.5,2)
\end{pspicture}
}{
dummy text
}
\end{document}