告诉 pgfplots 不要尝试绘制未定义函数的位置

告诉 pgfplots 不要尝试绘制未定义函数的位置

以下代码会引发错误,因为该函数未在域的一部分上定义(例如,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会(再次?)引发错误。

相关内容