更快地计算复杂函数

更快地计算复杂函数

我想用 绘制一些复杂的函数pgfplots。问题是绘制确实需要花费很多时间,尤其是一些子函数是重复的(计算多次)。例如

0.165*sin(2*x)-0.128*sin(x+5616/73)
cos(23.44*sin(x))

出现在多个位置上。

有没有什么办法可以优化计算,让绘图更快呢?

感谢您的建议。

\documentclass{minimal}
\usepackage{pgfplots}
\usepackage{filecontents}

\begin{document}

\def\anga{47} % latitude
\begin{tikzpicture}
\begin{axis}

\foreach \i in {-4,-3,...,4}{%
  \addplot[domain=0:360,samples=60] ({180+asin(cos(23.44*sin(x))*sin(15*(\i+0.165*sin(2*x)-0.128*sin(x+5616/73)))/sqrt(1-(sin(\anga)*sin(23.44*sin(x))+cos(\anga)*cos(23.44*sin(x))*cos(15*(\i+0.165*sin(2*x)-0.128*sin(x+5616/73))))^2))},{asin(sin(\anga)*sin(23.44*sin(x))+cos(\anga)*cos(23.44*sin(x))*cos(15*(\i+0.165*sin(2*x)-0.128*sin(x+5616/73))))});
}
\end{axis}
\end{tikzpicture}
\end{document}

答案1

gnuplot进行计算可能会快得多。在这种情况下,纯pgfplots代码通常在我的计算机上花费 5 秒多一点的时间,而gnuplot版本则花费 0.5 秒到 0.6 秒的时间。

它当然需要gnuplot安装,并且必须在shell-escape启用的情况下进行编译,例如pdflatex --shell-escape file.tex

\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}

\begin{document}

\def\anga{47} % latitude
\begin{tikzpicture}
\begin{axis}

\foreach \i in {-4,-3,...,4}{%
\addplot [black] gnuplot [raw gnuplot,id = p\i, mark=none] {
set parametric;
set trange [0:360];
set samples 60;
set angles degrees;
fx(t) = 180 + asin(cos(23.44*sin(t))*sin(15*(\i+0.165*sin(2*t) - 0.128*sin(t+5616/73)))/sqrt(1-(sin(\anga)*sin(23.44*sin(t)) + cos(\anga)*cos(23.44*sin(t))*cos(15*(\i+0.165*sin(2*t) - 0.128*sin(t+5616/73))))^2));
fy(t) = asin(sin(\anga)*sin(23.44*sin(t)) + cos(\anga)*cos(23.44*sin(t))*cos(15*(\i+0.165*sin(2*t) - 0.128*sin(t+5616/73))));
plot fx(t),fy(t)
};
}
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

以下是使用 LuaLaTeX 的解决方案:

\documentclass{minimal}
\usepackage{pgfplots}
\usepackage{filecontents}
\usepackage{luacode}

\begin{document}

\begin{luacode*}
anga=47 --  latitude
function sindeg(x)
    return math.sin(x*math.pi/180)
end
function cosdeg(x)
    return math.cos(x*math.pi/180)
end
function plot_curve(i)
    local N=60
    tex.sprint("\\addplot[line width=1pt,black] coordinates {")
    for theta=0,360,360/N do
        fct1=0.165*sindeg(2*theta)-0.128*sindeg(theta+5616/73)
        fct2=cosdeg(23.44*sindeg(theta))
        x=180+180/math.pi*math.asin(fct2*sindeg(15*(i+fct1))/math.sqrt(1-(sindeg(anga)*sindeg(23.44*sindeg(theta))+cosdeg(anga)*fct2*cosdeg(15*(i+fct1)))^2))
        y=180/math.pi*math.asin(sindeg(anga)*sindeg(23.44*sindeg(theta))+cosdeg(anga)*fct2*cosdeg(15*(i+fct1)))
        tex.sprint("("..x..","..y..")")
    end
    tex.print("};")
end
\end{luacode*}

\begin{tikzpicture}
\begin{axis}

\foreach \i in {-4,-3,...,4}{%
    \directlua{plot_curve(\i);}
}
\end{axis}
\end{tikzpicture}
\end{document}

由于 Lua 使用弧度表示角度,因此我必须重新定义弧度表示正弦和余弦函数。这样速度就非常快了。

当然你应该使用lualatex命令来编译它。

答案3

我感谢所有贡献者的回答。最后,我决定采用经典解决方案,即在 Python 中计算曲线点并导入它们。(我实际上以代码输出可以直接插入 .tex 的方式编写了程序,从而避免了另一个外部表。)

如果稍后出现更优雅的解决方案,我会接受它而不是我的。

相关内容