以下代码会引发错误,因为该函数未在域的一部分上定义(例如,acos
其参数不能大于 1):
\begin{tikzpicture}
\newcommand{\myfunc}[1]{acos(cos(sqrt(#1))+3*sin(sqrt(#1))/sqrt(#1))}
\begin{axis}[xmax={pi},xmin={-pi},xlabel={$ka$},xtick distance={pi/2},
xticklabels={,$-\pi$,$-\dfrac\pi2$,$0$,$\dfrac\pi2$,$\pi$},
ymax=40,ymin=0,ytick={-10},ylabel={$E_k$},ylabel style={rotate=-90},
trig format=rad]
\addplot[domain=0:40,smooth,samples=100,variable=\x] ({\myfunc\x},{\x});
\addplot[domain=0:40,smooth,samples=100,variable=\x] ({-\myfunc\x},{\x});
\end{axis}
\end{tikzpicture}
我必须用数字方式计算域。这将起作用:
\documentclass{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}
\newcommand{\myfunc}[1]{acos(cos(sqrt(#1))+3*sin(sqrt(#1))/sqrt(#1))}
\begin{axis}[xmax={pi},xmin={-pi},xlabel={$ka$},xtick distance={pi/2},
xticklabels={,$-\pi$,$-\dfrac\pi2$,$0$,$\dfrac\pi2$,$\pi$},
ymax=40,ymin=0,ytick={-10},ylabel={$E_k$},ylabel style={rotate=-90},
trig format=rad]
\addplot[domain=3.90648:9.8696,smooth,samples=20,variable=\x] ({\myfunc\x},{\x});
\addplot[domain=18.916:39.4784,smooth,samples=50,variable=\x] ({\myfunc\x},{\x});
\addplot[domain=3.90648:9.8696,smooth,samples=20,variable=\x] ({-\myfunc\x},{\x});
\addplot[domain=18.916:39.4784,smooth,samples=50,variable=\x] ({-\myfunc\x},{\x});
\end{axis}
\end{tikzpicture}
\end{document}
3.90648、9.8696 等数字是数值结果。我不喜欢这个,因为
- 我必须对数值进行硬编码;
- 该域是两个不连续的部分,所以我必须使用两个
\addplot
命令来绘制所有部分。
有什么办法可以让 pgfplots 忽略函数未定义的地方吗?
函数值为复数的点被视为超出定义域,我打算省略这些点(我只是想绘制实函数)。
该函数是
$$x=\pm\arccos!\left(\cos\sqrt{y}+3\frac{\sin\sqrt{y}}{\sqrt y}\right).$$
可以通过将上面指定段生成的图与 Mathematica 生成的输出进行比较来确认其正确性:
f[y_]=ArcCos[Cos[Sqrt[y]]+3Sin[Sqrt[y]]/Sqrt[y]]
ParametricPlot[{{f[y],y},{-f[y],y}},{y,0,40},AspectRatio -> 0.7]
答案1
这鼠尾草此软件包允许访问名为智者以及 Python 编程语言。CAS Sage 与 Mathematica 类似,只是它是免费的。因此,它将具有 Mathematica 所pgfplots
不具备的计算能力,并且该sagetex
软件包可让您将 Sage 数据和计算结果输入到 LaTeX 文档中。
你说,“3.90648、9.8696 等数字是数值结果。我不喜欢这个,因为
- 我必须对数值进行硬编码;
- 该域由两个不连续的部分组成,所以我必须使用两个 \addplot 命令来绘制所有部分。
使用的方法sagetex
避免了对数值进行硬编码,但无法避免 2 个 \addplot 命令。我认为这无法避免,因为 Mathematica 也使用了 2 个图:ParametricPlot[{{f[y],y},{-f[y],y}},{y,0,40},AspectRatio -> 0.7]
;第一部分由点 (f(y),y) 组成,第二部分由点 (-f(y),y) 组成。从 0<y<=40 绘制 f(y) 会给出图形的右半部分,因此当我尝试直接绘图时,它想将上半部分连接到下半部分:
因此,我尝试只绘制点而不连接它们。结果如下所示:
结果看起来好多了,但接近 0 时仍然存在问题。您需要弄清楚什么是您可以接受的。您可以尝试增加点的大小和/或通过减小步长来添加更多点。这是第二张图片中显示的代码:
\documentclass{article}
\usepackage{sagetex,amsmath,pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}
\begin{sagesilent}
t = var('t,y')
LowerY = 0
UpperY = 45
LowerX = -3.15
UpperX = 3.15
step = .01
########
xcoords1=[]
ycoords1=[]
xcoords2=[]
ycoords2=[]
f(y)=acos(cos(sqrt(y))+3*sin(sqrt(y))/sqrt(y))
for t in srange(0.01,40,step):
if f(t).is_real():
xcoords1+=[f(t).n(digits=4)]
ycoords1+=[t]
xcoords2+=[-f(t).n(digits=4)]
ycoords2+=[t]
output = r""
output += r"\begin{tikzpicture}"
output += r"\begin{axis}[xlabel={$ka$},xtick distance={pi/2},"
output += r"xticklabels={,$-\pi$,$-\dfrac{\pi}{2}$,$0$,$\dfrac{\pi}{2}$,$\pi$},ytick={-10},"
output += r"ylabel={$E_k$},ylabel style={rotate=-90},trig format=rad,"
output += r"xmin=%f,xmax=%f,ymin= %f,ymax=%f]"%(LowerX,UpperX,LowerY, UpperY)
output += r"\addplot[only marks,mark options={mark size=.5pt},blue] coordinates {"
for i in range(0,len(xcoords1)-1):
if (ycoords1[i])<LowerY or (ycoords1[i])>UpperY:
output += r"(%f , inf) "%(xcoords1[i])
else:
output += r"(%f , %f) "%(xcoords1[i],ycoords1[i])
output += r"};"
output += r"\addplot[only marks,mark options={mark size=.6pt}, orange] coordinates {"
for i in range(0,len(xcoords2)-1):
if (ycoords2[i])<LowerY or (ycoords2[i])>UpperY:
output += r"(%f , inf) "%(xcoords1[i])
else:
output += r"(%f , %f) "%(xcoords2[i],ycoords2[i])
output += r"};"
output += r"\end{axis}"
output += r"\end{tikzpicture}"
\end{sagesilent}
\begin{center}
\sagestr{output}
\end{center}
\end{document}
Python 做了很多工作。关键部分在这里:if f(t).is_real():
Sage 计算 f(t) 的值,如果是实数,则将其包含在点列表中。如果不是实数(因为它是复数),则它不会进行任何计算。
only marks,mark options={mark size=.6pt}
指示要使用的点的大小,“仅标记”指示它不连接任何点。代码:
if (ycoords2[i])<LowerY or (ycoords2[i])>UpperY: output += r"(%f , inf) "%(xcoords1[i])
通过将 y 值指定为无限大来删除不符合屏幕绘图参数的点。
您可以免费获得可钙帐户来尝试使用 Sage 和 LaTeX。如果效果不错,那么 Sage 可以下载到您的计算机上并连接到您的 LaTeX 发行版。
编辑:今天花了点时间进行调整。只需更改这些线条
output += r"\addplot[only marks,mark options={mark size=1pt},blue] coordinates {"
,
output += r"\addplot[only marks,mark options={mark size=1pt}, orange] coordinates {"
即可获得更大的点数,从而缩小顶部的差距,尽管底部的差距仍然存在。
答案2
这不是一个完整的解决方案,而是一种方法。
不要嵌套deg()
和rad()
,尝试使用r
告诉 PGF 传递给三角函数的值应解释为弧度的语法。我还建议声明一个 PGF 函数:
\documentclass[border=10pt]{standalone}
\usepackage{pgfplots, amsmath}
\pgfplotsset{
compat=1.18,
/pgf/declare function={
myfunc(\x)=rad(acos(cos(sqrt(\x) r)+3*sin(sqrt(\x) r)/sqrt(\x)));
}
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xmax={pi},
xmin={-pi},
xlabel={$ka$},
xtick distance={pi/2},
xticklabels={,$-\pi$,$-\dfrac{\pi}{2}$,$0$,$\dfrac{\pi}{2}$,$\pi$},
ymax=40,
ymin=0,
ytick={-10},
ylabel={$E_k$},
ylabel style={rotate=-90}
]
\addplot[
domain=0:40,
smooth,
samples=129,
unbounded coords=jump
] ({myfunc(x)},{x});
\addplot[
domain=0:40,
smooth,
samples=129,
unbounded coords=jump
] ({-1*myfunc(x)},{x});
\end{axis}
\end{tikzpicture}
\end{document}
附近有空隙X= 0,这可能是一个可以通过更改样本大小来解决的问题。我目前无法解释,为什么使用samples at
会(再次?)引发错误。