つれづれなる備忘録

日々の発見をあるがままに綴る

Texによる文書作成26 ~TikZ

以前LaTeXファインマンダイアグラムが作成できるTikz-Feynhandを紹介したか、今回はおおもとのTikzによる図の描画機能について紹介したい。

atatat.hatenablog.com

1. Tikzのロード

TikzはLaTeXで図をコマンドベースで描画するためのパッケージでTikz-FeynhandはTikzの図形描画機能を利用している。

公式マニュアルの最新版はTikz & PGF version 3.1.9aで1322ページもある

https://pgf-tikz.github.io/pgf/pgfmanual.pdf

Tikzのパッケージ自体はプリアンブル領域に\usepackage{tikz}でロードできるが、さまざまな機能を利用するにはtikzライブラリもロードする必要がある。 以下線の描画では座標点を取り扱うため、\usetikzlibrary{calc}として座標計算するcalcライブラリをロードしておく

\documentclass[dvipdfmx]{jsarticle}
\usepackage{graphicx}

\usepackage{tikz}
\usetikzlibrary{calc}

2. 直線の描画

描画を行うには\tikzに続けて描画コマンドを記述するか、tikzpicture環境内\begin{tikzpicture}~\end{tikzpicture}で描画コマンドを使用する。

例えば単純な直線を描画するには\draw (開始座標)--(終点座標);とする。

直線の描画:\par
\tikz \draw (0,0)--(2,0);

\begin{tikzpicture}
 \draw (1,-1)--(3,-1.5);
\end{tikzpicture}

"直線の描画"
直線の描画

座標点を複数指定すると、連続的に直線を描画できる。

連続直線: \par
\tikz \draw (0,0)--(2,1)--(3,-1);

これを利用すると閉じた多角形も描画できる。図形が閉じている場合は最終座標に--cycle;を加える。例えば三角形は

閉じた直線(三角形):\par
\tikz \draw (0,0)--(2,1)--(3,-1)--cycle;

"連続直線の描画"
連続直線の描画

高度な機能として垂線を引くこともできる。最初の行で直線を引いて、直線を引いた座標(0,0),(3,1)と垂線の開始点(1,1)を以下のように指定すると、座標を求めることなく垂線を引くことができる。

垂線: \par
\begin{tikzpicture}
 \draw (0,0)--(3,-1);
 \draw (1,1)--($(0,0)!(1,1)!(3,-1)$);
\end{tikzpicture}

"垂線の描画"
垂線の描画

3. 図形の描画

図形は\draw + 図形コマンドで描画できる。長方形は\draw (開始座標) rectangle (終点座標);、円は\draw circle (半径);、楕円はcircleを用いて \draw (0,0) circle [x radius=x半径, y radius=y半径, rotate=回転角];とする。

長方形: \par
\tikz \draw (0,0) rectangle (3,1);

円: \par
\tikz \draw(0,0) circle (1);

楕円:\par
\tikz \draw (0,0) circle [x radius=2, y radius=1, rotate=30];

"図形の描画"
図形の描画

4. 曲線の描画

 曲線としてまず円弧の描画方法を示す。1つ目は1つの座標と開始角度、終点角度、半径を指定する。2つ目は2つの座標と角度を指定する。 さらに\drawの回転オプションを利用して描画した円弧を回転させることができる。

円弧(座標) (偏角1,偏角2,半径):\par
\tikz \draw (0,0) arc (30:90:2);

円弧 (座標1) to [偏角1,偏角2] (座標2):\par
\tikz \draw (0,0) to [out=60,in=120] (3,0);

円弧 の回転:\par
\tikz \draw[rotate=45] (0,0) to [out=45,in=135] (2,0);

"円弧の描画"
円弧の描画

次に任意の曲線は、2つ目の円弧の描画方法と同じで、指定する座標が円弧にならないケースに相当する。逆に2つ目の方法は任意曲線の特定の組み合わせが円弧になっていた。

任意の曲線  (座標1) to [偏角1,偏角2] (座標2):\par
\tikz \draw (0,0) to [out=45,in=135] (2,2);

"任意曲線の描画"
任意曲線の描画

最後に放物線はparabola bendで指定する。具体的には\draw (座標1) parabola bend (頂点座標) (座標2)とする。

放物線:\par
\tikz \draw (-2,-2) parabola bend (0,0) (2,-2);

"放物線の描画"
放物線の描画

5. まとめ

 今回はLaTeXで図形を描画するTikzパッケージと基本的な描画方法について紹介した。

SymPyの使い方25 ~ PDE2

 今回も前回に続いてSymPyを用いて偏微分方程式を解くPDEツールについて紹介したい。

atatat.hatenablog.com

1. 偏微分方程式ソルバーpdsolveの制約

 前回触れたように現状はpdsolveは1次の偏微分のみ対応しており、2次以上は解くことができない。 試しに以下のように2次の偏微分方程式を定義して解こうとするとNotImplementedError: psolve: Cannot solve Derivativeと表示されエラーになる。

from sympy import Function, symbols, exp
from sympy.solvers.pde import checkpdesol, pdsolve, classify_pde

x,y=symbols('x y')
f=Function('f')
eq=f(x,y).diff(x,x)+f(x,y).diff(y,y)
eq
>Derivative(f(x, y), (x, 2)) + Derivative(f(x, y), (y, 2))
sol=pdsolve(eq)
>NotImplementedError: psolve: Cannot solve Derivative(f(x, y), (x, 2)) + Derivative(f(x, y), (y, 2)

2. 右辺含む任意の1次偏微分方程式

前回のpde_1st_linear_constant_coeff_homogeneous以外で右辺に任意関数がある場合も解くことができる。

 \displaystyle cf(x,y)+a\frac{\partial f(x,y)}{\partial x}+b\frac{\partial f(x,y)}{\partial y}=g(x,y)

g=Function('g')
a,b,c=symbols('a b c')
gen1_eq=a*f(x,y).diff(x)+b*f(x,y).diff(y)+c*f(x,y)-g(x,y)

pdsolveで解くと、少し時間がかかって以下のように解が表示される。

sol_gen1=pdsolve(gen1_eq)
sol_gen1
>Eq(f(x, y), ((a**2 + b**2)*F(-a*y + b*x) + Integral(g(-a*b*y/(a**2 + b**2) + a*xi/(a**2 + b**2) + b**2*x/(a**2 + b**2), a**2*y/(a**2 + b**2) - a*b*x/(a**2 + b**2) + b*xi/(a**2 + b**2))*exp(c*xi/(a**2 + b**2)), (xi, a*x + b*y)))*exp(-c*(a*x + b*y)/(a**2 + b**2))/(a**2 + b**2))

上を少し整えると

 \displaystyle f(x,y)=\left( F(\eta)+\frac{\int^{\eta} g (\alpha,\beta) \exp ( \frac{c\xi}{a^{2}+b^{2}} ) d\xi }{a^{2}+b^{2}} \right)  \exp \left( \frac{c\xi}{a^{2}+b^{2}} \right)

 \displaystyle \xi=ax+by, \eta=-ay+bx

 \displaystyle \alpha=\frac{a\xi+b\eta}{a^{2}+b^{2}},\beta=\frac{-a\eta+b\xi}{a^{2}+b^{2}}

classify_pdeで方程式の型を表示すると1st_linear_constant_coeff_Integralが得られる。

classify_pde(gen1_eq)
>('1st_linear_constant_coeff', '1st_linear_constant_coeff_Integral')

dsolveのときと同様にhintオプションで1st_linear_constant_coeff_Integralを指定すると処理が早くなる。

sol_gen1=pdsolve(gen1_eq,hint='1st_linear_constant_coeff_Integral')

係数a,b,cやg(x,y)が任意でない場合は、hintオプションなしでも即座に解が計算される。

gen1_eq2= f(x,y).diff(x) + f(x,y).diff(y) + f(x,y) - exp(x + y)
sol2_gen1=pdsolve(gen1_eq2)
sol2_gen1
>Eq(f(x, y), F(x - y)*exp(-x/2 - y/2) + exp(x + y)/3

3. 係数が関数の場合

 係数a,b,cが以下のように関数の場合もpdsolveで解ける

 \displaystyle c(c,y)f(x,y)+a(x,y)\frac{\partial f(x,y)}{\partial x}+b(x,y)\frac{\partial f(x,y)}{\partial y}=g(x,y)

ただし、上の偏微分方程式をそのまま解こうとすると非常に時間がかかるので、具体的にそれぞれ関数を指定したものを解いてみる。

gen2_eq=x*(f(x,y).diff(x)) - y*(f(x,y).diff(y)) + y**2*f(x,y) - y**2
classify_pde(gen2_eq)
>('1st_linear_variable_coeff',)

方程式の型は1st_linear_variable_coeffとなる。以下hintは指定しなくてもあまり時間は変わらないが、pdsolveで解が得られる。

 sol_gen2=pdsolve(gen2_eq,hint='1st_linear_variable_coeff')
 sol_gen2
>Eq(f(x, y), F(x*y)*exp(y**2/2) + 1)

4. まとめ

 今回はSimPyのpdfsolveを用いていろいろな1次偏微分方程式の解を得る方法について紹介した。

SymPyの使い方24 ~ PDE

 今回はSymPyを用いて偏微分方程式を解くPDEツールについて紹介したい。 基本的には以前紹介した微分方程式を解く方法と似ているが、現状1次のPDEなど制約が多いようだ。

atatat.hatenablog.com

1. 偏微分方程式ソルバーpdsolve

 微分方程式ではdsolveを用いていたが。偏微分方程式ではpdsolveを用いる。手順は偏微分方程式eqを定義して、pdsolve(eq)とすれば解が得られる。

以下の偏微分方程式

 \displaystyle 2f(x,y)+3\frac{\partial f(x,y)}{\partial x}+2\frac{\partial f(x,y)}{\partial y}=0

を解く。

まず今回利用するモジュール、関数を以下のようにロードする。

from sympy import Function, symbols, exp
from sympy.solvers.pde import checkpdesol, pdsolve, classify_pde

次にシンボリック変数、関数を定義し、上の偏微分方程式eqとして定義する。

x,y=symbols('x y')
f=Function('f')
eq=2*f(x,y)+3*f(x,y).diff(x)+4*f(x,y).diff(y)
eq
>2*f(x, y) + 3*Derivative(f(x, y), x) + 4*Derivative(f(x, y), y)

pdsolve(eq)とすれば解が得られる。

sol=pdsolve(eq)
sol
>Eq(f(x, y), F(4*x - 3*y)*exp(-6*x/25 - 8*y/25))

偏微分方程式の解は

 \displaystyle f(x,y)=F(4x-3y)\exp \left( -\frac{6x}{25}-\frac{8y}{25} \right)

ということがわかる。

2. 解の確認

基本的にpdsolveで得られた解は偏微分方程式を満たすが、偏微分の性質から微分方程式よりもさまざまな解が候補になりえる。 そこで解が偏微分方程式を満たしているかどうかchkpdesol(eq,sol)で確認することができる。満たしていればTrue,満たしていなければFalseが返される。

まず、pdsolveで得られた解でチェックする。

checkpdesol(eq,sol)
>(True, 0)

解のうちF(4*x-3*y)は任意の関数を指定できるので、例えばF(x,y)=(4*x - 3*y)が解になっているか確認するには

 sol1= (4*x - 3*y)*exp(-6*x/25 - 8*y/25)
checkpdesol(eq,sol1)
>(True, 0)

同様にF(x,y)=(4*x - 3*y)**2とした場合も

sol2= (4*x - 3*y)**2*exp(-6*x/25 - 8*y/25)
checkpdesol(eq,sol2)
>(True, 0)

さらに線形関数以外を選択する場合、例えばF(x,y)=exp(4*x - 3*y)

sol3= exp(4*x - 3*y)*exp(-6*x/25 - 8*y/25)
checkpdesol(eq,sol3)
>(True, 0)

任意の関数の引数が4*x-3*y以外だと偏微分方程式は満たさない。例えばF(x,y)=exp(4*x-3)とすると

sol4= exp(4*x-3)*exp(-6*x/25 - 8*y/25)
checkpdesol(eq,sol4)
>(False, 12*exp(94*x/25 - 8*y/25 - 3))

3. 任意定数の偏微分方程式

上で解いた偏微分方程式の係数を任意の定数にした場合も同様に解が得られる。

 \displaystyle a\frac{\partial f(x,y)}{\partial x}+b\frac{\partial f(x,y)}{\partial y}+cf(x,y)=0

a,b,cをシンボリック変数として定義して、上と同様にpdsolve()を適用する。

a,b,c=symbols('a b c')
eq_gen=a*f(x,y).diff(x)+b*f(x,y).diff(y)+c*f(x,y)
sol_gen=pdsolve(eq_gen)
sol_gen
>Eq(f(x, y), F(-a*y + b*x)*exp(-c*(a*x + b*y)/(a**2 + b**2)))

得られる解は

 \displaystyle f(x,y)=F(bx-ay)\exp \left( -\frac{c ( ax+by) }{a^{2}+b^{2}} \right)

上の場合はa=3,b=4,c=2だったので一般解になっている。

最後にclassify_pdeにより偏微分方程式の分類を表示させることができる。今回解いた方程式は1st_linear_constant_coeff_homogeneousとなっている。

classify_pde(eq_gen)
>('1st_linear_constant_coeff_homogeneous',)

4. まとめ

 SimPyのpdfsolveにより条件付きながら偏微分方程式の解を得る方法について紹介した。