LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

TeX&TikZで数値計算して動画もつくる【準備】(編集中)

TeXで数値計算をしたくなったら

TeXで数値計算をしたくなったら,この記事の内容を試してみてはいかがでしょうか。TeX&TikZで数値計算と絵の描画の両方ができます。主はプログラミング素人で,ごくたまに趣味でTeXを使います。書き方や変数のネーミングセンスはご容赦ください。

TeXはPDFを作成するところまでの処理ができます。ここまでの処理でパラパラ漫画を作ります。これを動画ファイルにすることで動画作りができます。

たとえばこんな感じ
https://youtu.be/7y507cBemnM
IMAGE ALT TEXT HERE

動画作成までの流れ

TeX処理→PDF作成

PDF→PNG画像(poppler cairo)

PNG画像→mp4(aviutl)

TeXで書くこと(概略)

大きく分けると,次のようなパーツで構成します。

  1. パラメータ・初期値・その他必要な定義
  2. tikzで描画
  3. 数値計算
  4. \newpage

2~4の内容を繰り返し実行させます。4.を忘れてしまうと,パラパラ漫画にならないので注意です。またpreview環境を使って,図の部分の切り抜きを行います。

1~4の順番でTeXに書く内容を書いていきます。

カウンターの設置・パラメータ・初期値(変数の設置)

繰り返し処理(ループ)をするために,カウンターを定義しておく。

%カウンター定義
        \newcount\countA%

同時に何回繰り返すかをここで定義しておく。TeXマクロを定義する\defを使う。

%%%#1 %分割数
\def\stepA{10}%Total Time70

カウンター・loop関係の設定

%カウンター定義
        \newcount\countA%.......................
        \newcount\countB%..........................
        \newcount\countC%..........................
%%%#1 %分割数
\def\stepC{3}%内部計算3
\def\stepB{10}%フレーム数 10 予定
\def\stepA{140}%Total Time70

補助的なカウンター

\newcount\InnerCount%多粒子系用
\global\edef\TrajCount{1}%軌道残像よう カウンターではない

パラメータ設定

%%%%%%%%%%%%%%%%%%%%%%%%%
%物理パラメータ 定数
%粒子数の設定
%%%%%%%%%%%%%%%%%%%%%%%%%
        \tikzmath{
        real \PI;
            \PI = 3.1415;
        real \grav;
            \grav = 0.02;
        real \MASS;
            \MASS = 10;
            \freqS = 2*\PI/ 32;
        int \ParNum ;
       \ParNum=5; %粒子数
        }

tikzにはpiという定数関数が存在します。知らないときにつくったコードなので,その名残りです。

初期値・変数の設定

\tikzmath{
    real
    \NqiXMonkey \NqiYMonkey \NviXMonkey \NviYMonkey;
    \NqiXMonkey = ...;
    \NqiYMonkey = ...;
    \NviXMonkey = ...;
    \NviYMonkey = ...;
}

%サルの初期位置
\global\edef\variXCdMonkey{\NqiXMonkey}%初期値を定める
\global\edef\variYCdMonkey{\NqiYMonkey}%初期値を定める
%サルの初速度
\def\variXVelocityMonkey{\NviXMonkey}
\def\variYVelocityMonkey{\NviYMonkey}

微分方程式に登場する関数の定義

%力・加速度関数
    \def\funcAccelMX#1#2#3#4{....}
    \def\funcAccelMY#1#2#3#4{....}

loop

\countA = 0 \loop\ifnum\countA < \stepA
{
\countB = 0 \loop\ifnum\countB < \stepB
{

%tikzの描画
\begin{tikzpicture}

\end{tikzpicture}




%ルンゲクッタ計算パート
\countC = 0 \loop\ifnum\countC < \stepC
{
}
\advance\countB by1\repeat % end for




\newpage 
}\advance\countB by1\repeat % end for                                                                                  
}\advance\countA by1\repeat % end for                                                                                  

通常3つのカウンターを用いて,3つのループを入れ子にして使用しています。PDFのページはstepA×stepBページ生成されます。\countCによるloopは,計算精度を上げるために使用したりします。必要ない場合は\def\stepC{1}とします。

tikzpicture

\begin{tikzpicture}


%背景
\draw[gray] (0,0,0) -- (20,0,0) (0,0,0) -- (-20,0,0) (0,0,0) -- (0,20,0) (0,0,0) -- (0,-20,0);

\foreach \x in {1,...,20}
{
    \draw[gray] (0,0,0) circle (\x*\DiscR cm);
}


%いろいろ書きます



\end{tikzpicture}

ルンゲクッタ計算部分

初期値を代入

%ルンゲクッタ開始
%サル用 初期値代入
\tikzmath{
    \NqtXTako = \variXCdMonkey;
    \NqtYTako = \variYCdMonkey;
    \NvtXTako = \variXVelocityMonkey;
    \NvtYTako = \variYVelocityMonkey;
}

計算パート(運動方程式を積分・2次のルンゲクッタの方法に基づく)

\tikzmath{
%半ステップ後の速度を計算するよ
    real \variFuji;
    \variFuji1=\NqtXTako;
    \variFuji2=\NqtYTako;
    \variFuji3=\NvtXTako;
    \variFuji4=\NvtYTako;
    \NatXTako = \funcAccelMX{\variFuji1}{\variFuji2}{\variFuji3}{\variFuji4};
    \NatYTako = \funcAccelMY{\variFuji1}{\variFuji2}{\variFuji3}{\variFuji4};
    %
    \variFuji1=\NqtXTako + 0.25 * \NvtXTako *\dT /\stepC;
    \variFuji2=\NqtYTako + 0.25 * \NvtYTako *\dT /\stepC;
    \variFuji3=\NvtXTako + 0.25 * \NatXTako * \dT /\stepC;
    \variFuji4=\NvtYTako + 0.25 * \NatYTako * \dT /\stepC;
    \NatXTako = \funcAccelMX{\variFuji1}{\variFuji2}{\variFuji3}{\variFuji4};
    \NatYTako = \funcAccelMY{\variFuji1}{\variFuji2}{\variFuji3}{\variFuji4};
    %
    \NvthXTako = \NvtXTako + 0.5 * \dT / \stepC * \NatXTako;
    \NvthYTako = \NvtYTako + 0.5 * \dT / \stepC * \NatYTako;
    %
    %
%%1ステップ後の速度を計算するよ
    \variFuji1=\NqtXTako;
    \variFuji2=\NqtYTako;
    \variFuji3=\NvtXTako;
    \variFuji4=\NvtYTako;
    \NatXTako = \funcAccelMX{\variFuji1}{\variFuji2}{\variFuji3}{\variFuji4};
    \NatYTako = \funcAccelMY{\variFuji1}{\variFuji2}{\variFuji3}{\variFuji4};
    %
    \variFuji1=\NqtXTako + 0.5 * \NvtXTako *\dT /\stepC;
    \variFuji2=\NqtYTako + 0.5 * \NvtYTako *\dT /\stepC;
    \variFuji3=\NvtXTako + 0.5 * \NatXTako * \dT /\stepC;
    \variFuji4=\NvtYTako + 0.5 * \NatYTako * \dT /\stepC;
    %%
    \NatXTako = \funcAccelMX{\variFuji1}{\variFuji2}{\variFuji3}{\variFuji4};
    \NatYTako = \funcAccelMY{\variFuji1}{\variFuji2}{\variFuji3}{\variFuji4};
    %%
    \NvtXTako = \NvtXTako +  \dT / \stepC * \NatXTako;
    \NvtYTako = \NvtYTako +  \dT / \stepC * \NatYTako;
%%位置座標の計算をするよ。
    \NqtXTako = \NqtXTako + \NvthXTako * \dT / \stepC;
    \NqtYTako = \NqtYTako + \NvthYTako * \dT / \stepC;
}

計算結果代入

%サルの位置
    \global\edef\variXCdMonkey{\NqtXTako}%次の初期値を定める
    \global\edef\variYCdMonkey{\NqtYTako}%次の初期値を定める
%サルの速度
    \global\edef\variXVelocityMonkey{\NvtXTako}
    \global\edef\variYVelocityMonkey{\NvtYTako}

繰り返し計算(ループ)について

カウンターを設置し,カウンターの値を参照して繰り返しを実現します。カウンターの設置とループ部分の2つで構成します。

カウンターの設置

\newcount\countA

ループ部分

\def\stepA{140}%Total Time70
\countA = 0 \loop\ifnum\countA < \stepA%ループ開始
{
%
%ここに繰り返す部分を書く
%
}\advance\countA by1\repeat %ループ終了                                                                             

\loop\repeatの組み合わせで使います。上の例の場合,まず\countA=0でカウンターにゼロが代入されます。\ifnum\countA < \stepAでは\countA\stepAよりも小さい(条件分岐)ときにして実行されます。この条件を満たさないとき,\loopないの処理が終了します。
\advance\countA by1で,カウンター\countAに1を足します。\repeatから\loopに戻り,再び分岐のふるいにかけます。

このループの中には,\begin{tikzpicture}による描画と数値計算,\newpageを入れておきます。

カウンターについてはこちら
https://qiita.com/hironarin/items/2e40bac56a9fee727ed1

パラメータの設置・計算について

数値の代入・計算には\tikzmathを使います。例えば,

\tikzmath{
        real \grav;
            \grav = 0.02;
        real \MASS;
            \MASS = 10;
        int \ParNum ;
       \ParNum=5; %粒子数
}

realで実数,intで整数の変数を設定できます。実数は小数点付きの数値,整数はそのまま。何も宣言しないまま

\tikzmath{ \a = 10;}

と書くと,実数と認識されます。

注意:\tikzmathの中に空行を入れてはいけません。エラーが出ます。行の最後に;を書きます。

変数の設置について

初期値を入れたり,計算結果の入出力をするための変数を設置します。設置の方法は,TeXのマクロ作成でおなじみの\defを使います。\defは,既にあるマクロを上書きしてくれる性質があるのでちょうどよのです。ただし,ちょっと工夫が必要で,バカの一つ覚えで,次の形で使います。名前のつけ方についてはご容赦ください。

\global\edef\variXCdMonkey{10}%初期値を定める
\global\edef\variYCdMonkey{20}%初期値を定める

もしくは,

\tikzmath{
    \NqiXMonkey = 10;
    \NqiYMonkey = 20;
}
\global\edef\variXCdMonkey{\NqiXMonkey}%初期値を定める
\global\edef\variYCdMonkey{\NqiYMonkey}%初期値を定める

上の例では2つの変数を定義しています。

ちょっと説明

\def\variable{100}

通常,マクロはコマンドの列として実行されます。数値計算では「数値」を覚えさせたいものです。数値を覚えさせるために\edefを使用します。たとえば,

\tikzmath{
\Monkey = 10;
}
\edef\variable{\Monkey}

変数を定義するとき,\tikzmathを使ってもできそうな気がしますが注意が必要です。\loop内で計算した結果,定義しなおした値は,1回の\loop内でのみ有効で,1回終わるごとにその数値を忘れてしまいます(たぶんローカル変数)。数値を全体で有効にするために\globalをつけます。

\tikzmath{
\Monkey = 10;
}
\global\edef\variable{\Monkey}

これで,\variableが上書きされない限りその数値が有効です。

条件分岐について

\ifthenelseを使います。スタイルファイルの宣言が必要です。

\usepackage{ifthen}

こっちで書いてます
https://qiita.com/hironarin/items/ae62b386dc921cdf38f4

エラーが出たとき疑うこと

Undefined control sequenceと言われた場合は,定義されていないトークンがある

\tikzmath内に空行がある
\tikzmath内で;を書いていない。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2